ogserver/src/rest.c

9167 lines
229 KiB
C

/*
* Copyright (C) 2020-2021 Soleta Networks <info@soleta.eu>
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*/
#include "ogAdmServer.h"
#include "dbi.h"
#include "utils.h"
#include "list.h"
#include "rest.h"
#include "core.h"
#include "wol.h"
#include "cfg.h"
#include "schedule.h"
#include "legacy.h"
#include <ev.h>
#include <syslog.h>
#include <sys/ioctl.h>
#include <ifaddrs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <jansson.h>
#include <dirent.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/statvfs.h>
#include <sys/sysinfo.h>
struct ev_loop *og_loop;
#define OG_REST_PARAM_ADDR (1UL << 0)
#define OG_REST_PARAM_MAC (1UL << 1)
#define OG_REST_PARAM_WOL_TYPE (1UL << 2)
#define OG_REST_PARAM_RUN_CMD (1UL << 3)
#define OG_REST_PARAM_DISK (1UL << 4)
#define OG_REST_PARAM_PARTITION (1UL << 5)
#define OG_REST_PARAM_REPO (1UL << 6)
#define OG_REST_PARAM_NAME (1UL << 7)
#define OG_REST_PARAM_ID (1UL << 8)
#define OG_REST_PARAM_CODE (1UL << 9)
#define OG_REST_PARAM_TYPE (1UL << 10)
#define OG_REST_PARAM_PROFILE (1UL << 11)
#define OG_REST_PARAM_CACHE (1UL << 12)
#define OG_REST_PARAM_CACHE_SIZE (1UL << 13)
#define OG_REST_PARAM_PART_0 (1UL << 14)
#define OG_REST_PARAM_PART_1 (1UL << 15)
#define OG_REST_PARAM_PART_2 (1UL << 16)
#define OG_REST_PARAM_PART_3 (1UL << 17)
#define OG_REST_PARAM_SYNC_SYNC (1UL << 18)
#define OG_REST_PARAM_SYNC_DIFF (1UL << 19)
#define OG_REST_PARAM_SYNC_REMOVE (1UL << 20)
#define OG_REST_PARAM_SYNC_COMPRESS (1UL << 21)
#define OG_REST_PARAM_SYNC_CLEANUP (1UL << 22)
#define OG_REST_PARAM_SYNC_CACHE (1UL << 23)
#define OG_REST_PARAM_SYNC_CLEANUP_CACHE (1UL << 24)
#define OG_REST_PARAM_SYNC_REMOVE_DST (1UL << 25)
#define OG_REST_PARAM_SYNC_DIFF_ID (1UL << 26)
#define OG_REST_PARAM_SYNC_DIFF_NAME (1UL << 27)
#define OG_REST_PARAM_SYNC_PATH (1UL << 28)
#define OG_REST_PARAM_SYNC_METHOD (1UL << 29)
#define OG_REST_PARAM_ECHO (1UL << 30)
#define OG_REST_PARAM_TASK (1UL << 31)
#define OG_REST_PARAM_TIME_YEARS (1UL << 32)
#define OG_REST_PARAM_TIME_MONTHS (1UL << 33)
#define OG_REST_PARAM_TIME_WEEKS (1UL << 34)
#define OG_REST_PARAM_TIME_WEEK_DAYS (1UL << 35)
#define OG_REST_PARAM_TIME_DAYS (1UL << 36)
#define OG_REST_PARAM_TIME_HOURS (1UL << 37)
#define OG_REST_PARAM_TIME_AM_PM (1UL << 38)
#define OG_REST_PARAM_TIME_MINUTES (1UL << 39)
#define OG_REST_PARAM_NETMASK (1UL << 40)
#define OG_REST_PARAM_SCOPE (1UL << 41)
#define OG_REST_PARAM_MODE (1UL << 42)
#define OG_REST_PARAM_CENTER (1UL << 43)
#define OG_REST_PARAM_BACKUP (1UL << 44)
#define OG_REST_PARAM_ROOM (1UL << 45)
#define OG_REST_PARAM_GATEWAY (1UL << 46)
#define OG_REST_PARAM_FOLDER (1UL << 47)
static LIST_HEAD(client_list);
static LIST_HEAD(client_wol_list);
void og_client_add(struct og_client *cli)
{
list_add(&cli->list, &client_list);
}
struct og_client *__og_client_find(const struct in_addr *addr)
{
struct og_client *client;
list_for_each_entry(client, &client_list, list) {
if (!client->agent)
continue;
if (client->addr.sin_addr.s_addr == addr->s_addr)
return client;
}
return NULL;
}
static struct og_client *og_client_find(const char *ip)
{
struct in_addr addr;
int res;
res = inet_aton(ip, &addr);
if (!res) {
syslog(LOG_ERR, "Invalid IP string: %s\n", ip);
return NULL;
}
return __og_client_find(&addr);
}
static const char *og_client_status(const struct og_client *cli)
{
switch (cli->last_cmd) {
case OG_CMD_UNSPEC:
case OG_CMD_PROBE:
break;
default:
return "BSY";
}
switch (cli->status) {
case OG_CLIENT_STATUS_BUSY:
return "BSY";
case OG_CLIENT_STATUS_OGLIVE:
return "OPG";
case OG_CLIENT_STATUS_VIRTUAL:
return "VDI";
case OG_CLIENT_STATUS_LINUX:
return "LNX";
case OG_CLIENT_STATUS_LINUX_SESSION:
return "LNXS";
case OG_CLIENT_STATUS_WIN:
return "WIN";
case OG_CLIENT_STATUS_WIN_SESSION:
return "WINS";
default:
return "OFF";
}
}
static bool og_msg_params_validate(const struct og_msg_params *params,
const uint64_t flags)
{
return (params->flags & flags) == flags;
}
static bool og_flags_validate(const uint64_t flags,
const uint64_t required_flags)
{
return (flags & required_flags) == required_flags;
}
static int og_json_parse_clients(json_t *element, struct og_msg_params *params)
{
unsigned int i;
json_t *k;
if (json_typeof(element) != JSON_ARRAY)
return -1;
for (i = 0; i < json_array_size(element); i++) {
k = json_array_get(element, i);
if (json_typeof(k) != JSON_STRING)
return -1;
params->ips_array[params->ips_array_len++] =
json_string_value(k);
params->flags |= OG_REST_PARAM_ADDR;
}
return 0;
}
int og_json_parse_partition_setup(json_t *element, struct og_msg_params *params)
{
unsigned int i;
json_t *k;
if (json_typeof(element) != JSON_ARRAY)
return -1;
for (i = 0; i < json_array_size(element) && i < OG_PARTITION_MAX; ++i) {
k = json_array_get(element, i);
if (json_typeof(k) != JSON_OBJECT)
return -1;
if (og_json_parse_partition(k, &params->partition_setup[i],
OG_PARAM_PART_NUMBER |
OG_PARAM_PART_CODE |
OG_PARAM_PART_FILESYSTEM |
OG_PARAM_PART_SIZE |
OG_PARAM_PART_FORMAT) < 0)
return -1;
params->flags |= (OG_REST_PARAM_PART_0 << i);
}
return 0;
}
static int og_json_parse_time_params(json_t *element,
struct og_msg_params *params)
{
const char *key;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "years")) {
err = og_json_parse_uint(value, &params->time.years);
params->flags |= OG_REST_PARAM_TIME_YEARS;
} else if (!strcmp(key, "months")) {
err = og_json_parse_uint(value, &params->time.months);
params->flags |= OG_REST_PARAM_TIME_MONTHS;
} else if (!strcmp(key, "weeks")) {
err = og_json_parse_uint(value, &params->time.weeks);
params->flags |= OG_REST_PARAM_TIME_WEEKS;
} else if (!strcmp(key, "week_days")) {
err = og_json_parse_uint(value, &params->time.week_days);
params->flags |= OG_REST_PARAM_TIME_WEEK_DAYS;
} else if (!strcmp(key, "days")) {
err = og_json_parse_uint(value, &params->time.days);
params->flags |= OG_REST_PARAM_TIME_DAYS;
} else if (!strcmp(key, "hours")) {
err = og_json_parse_uint(value, &params->time.hours);
params->flags |= OG_REST_PARAM_TIME_HOURS;
} else if (!strcmp(key, "am_pm")) {
err = og_json_parse_uint(value, &params->time.am_pm);
params->flags |= OG_REST_PARAM_TIME_AM_PM;
} else if (!strcmp(key, "minutes")) {
err = og_json_parse_uint(value, &params->time.minutes);
params->flags |= OG_REST_PARAM_TIME_MINUTES;
}
if (err != 0)
return err;
}
return err;
}
static const char *og_cmd_to_uri[OG_CMD_MAX] = {
[OG_CMD_WOL] = "wol",
[OG_CMD_PROBE] = "probe",
[OG_CMD_SHELL_RUN] = "shell/run",
[OG_CMD_SESSION] = "session",
[OG_CMD_POWEROFF] = "poweroff",
[OG_CMD_REFRESH] = "refresh",
[OG_CMD_REBOOT] = "reboot",
[OG_CMD_STOP] = "stop",
[OG_CMD_HARDWARE] = "hardware",
[OG_CMD_SOFTWARE] = "software",
[OG_CMD_IMAGE_CREATE] = "image/create",
[OG_CMD_IMAGE_UPDATE] = "image/update",
[OG_CMD_IMAGE_RESTORE] = "image/restore",
[OG_CMD_SETUP] = "setup",
[OG_CMD_RUN_SCHEDULE] = "run/schedule",
[OG_CMD_IMAGES] = "images",
[OG_CMD_CACHE_DELETE] = "cache/delete",
};
static bool og_client_is_busy(const struct og_client *cli,
enum og_cmd_type type)
{
switch (type) {
case OG_CMD_REBOOT:
case OG_CMD_POWEROFF:
case OG_CMD_STOP:
break;
default:
if (cli->last_cmd != OG_CMD_UNSPEC)
return true;
break;
}
return false;
}
int og_send_request(enum og_rest_method method, enum og_cmd_type type,
const struct og_msg_params *params,
const json_t *data)
{
const char *content_type = "Content-Type: application/json";
char content [OG_MSG_REQUEST_MAXLEN - 700] = {};
char buf[OG_MSG_REQUEST_MAXLEN] = {};
unsigned int content_length;
char method_str[5] = {};
struct og_client *cli;
const char *uri;
unsigned int i;
int client_sd;
bool has_seq;
if (method == OG_METHOD_GET)
snprintf(method_str, 5, "GET");
else if (method == OG_METHOD_POST)
snprintf(method_str, 5, "POST");
else
return -1;
if (!data)
content_length = 0;
else
content_length = json_dumpb(data, content,
OG_MSG_REQUEST_MAXLEN - 700,
JSON_COMPACT | JSON_ENSURE_ASCII);
uri = og_cmd_to_uri[type];
switch (type) {
case OG_CMD_POWEROFF:
case OG_CMD_REBOOT:
case OG_CMD_STOP:
has_seq = false;
break;
default:
has_seq = true;
break;
}
for (i = 0; i < params->ips_array_len; i++) {
cli = og_client_find(params->ips_array[i]);
if (!cli)
continue;
if (og_client_is_busy(cli, type))
continue;
client_sd = cli->io.fd;
if (client_sd < 0) {
syslog(LOG_INFO, "Client %s not conected\n",
params->ips_array[i]);
continue;
}
if (++cli->seq == 0)
cli->seq++;
snprintf(buf, OG_MSG_REQUEST_MAXLEN,
"%s /%s HTTP/1.1\r\nContent-Length: %d\r\nX-Sequence: %u\r\n%s\r\n\r\n%s",
method_str, uri, content_length, has_seq ? cli->seq : 0, content_type, content);
if (send(client_sd, buf, strlen(buf), 0) < 0)
continue;
cli->last_cmd = type;
}
json_decref((json_t *)data);
return 0;
}
static int og_cmd_post_clients(json_t *element, struct og_msg_params *params)
{
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
return og_send_request(OG_METHOD_POST, OG_CMD_PROBE, params, NULL);
}
struct og_buffer {
char *data;
int len;
};
#define OG_MSG_RESPONSE_MAXLEN 262144
static int og_json_dump_clients(const char *buffer, size_t size, void *data)
{
struct og_buffer *og_buffer = (struct og_buffer *)data;
if (size >= OG_MSG_RESPONSE_MAXLEN - og_buffer->len) {
syslog(LOG_ERR, "Response JSON body is too large\n");
return -1;
}
memcpy(og_buffer->data + og_buffer->len, buffer, size);
og_buffer->len += size;
return 0;
}
static const char *og_cmd_result_str_array[] = {
[OG_UNKNOWN] = "unknown",
[OG_FAILURE] = "failure",
[OG_SUCCESS] = "success",
};
static const char *og_cmd_result_str(const enum og_cmd_result result)
{
if (result > OG_SUCCESS)
return "unknown";
return og_cmd_result_str_array[result];
}
static json_t *og_json_client_cmd_result(const enum og_cmd_result result)
{
const char *result_str;
json_t *last_cmd;
last_cmd = json_object();
result_str = og_cmd_result_str(result);
json_object_set_new(last_cmd, "result", json_string(result_str));
return last_cmd;
}
static int og_json_client_append(json_t *array, struct og_client *client)
{
json_t *addr, *state, *last_cmd, *object;
object = json_object();
if (!object)
return -1;
addr = json_string(inet_ntoa(client->addr.sin_addr));
if (!addr) {
json_decref(object);
return -1;
}
json_object_set_new(object, "addr", addr);
state = json_string(og_client_status(client));
if (!state) {
json_decref(object);
return -1;
}
json_object_set_new(object, "state", state);
json_object_set_new(object, "speed", json_integer(client->speed));
last_cmd = og_json_client_cmd_result(client->last_cmd_result);
json_object_set_new(object, "last_cmd", last_cmd);
json_array_append_new(array, object);
return 0;
}
static int og_json_client_wol_append(json_t *array,
struct og_client_wol *cli_wol)
{
json_t *addr, *state, *last_cmd, *object;
object = json_object();
if (!object)
return -1;
addr = json_string(inet_ntoa(cli_wol->addr));
if (!addr) {
json_decref(object);
return -1;
}
json_object_set_new(object, "addr", addr);
state = json_string(og_client_wol_status(cli_wol));
if (!state) {
json_decref(object);
return -1;
}
json_object_set_new(object, "state", state);
last_cmd = og_json_client_cmd_result(OG_UNKNOWN);
json_object_set_new(object, "last_cmd", last_cmd);
json_array_append_new(array, object);
return 0;
}
static int og_cmd_get_clients(json_t *element, struct og_msg_params *params,
char *buffer_reply)
{
struct og_buffer og_buffer = {
.data = buffer_reply,
};
struct og_client_wol *cli_wol;
struct og_client *client;
json_t *array, *root;
array = json_array();
if (!array)
return -1;
list_for_each_entry(cli_wol, &client_wol_list, list) {
if (og_json_client_wol_append(array, cli_wol) < 0) {
json_decref(array);
return -1;
}
}
list_for_each_entry(client, &client_list, list) {
if (!client->agent)
continue;
if (og_json_client_append(array, client) < 0) {
json_decref(array);
return -1;
}
}
root = json_pack("{s:o}", "clients", array);
if (!root) {
json_decref(array);
return -1;
}
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
static int og_json_parse_type(json_t *element, struct og_msg_params *params)
{
const char *type;
if (json_typeof(element) != JSON_STRING)
return -1;
params->wol_type = json_string_value(element);
type = json_string_value(element);
if (!strcmp(type, "unicast"))
params->wol_type = "2";
else if (!strcmp(type, "broadcast"))
params->wol_type = "1";
params->flags |= OG_REST_PARAM_WOL_TYPE;
return 0;
}
struct og_client_wol *og_client_wol_find(const struct in_addr *addr)
{
struct og_client_wol *cli_wol;
list_for_each_entry(cli_wol, &client_wol_list, list) {
if (cli_wol->addr.s_addr == addr->s_addr)
return cli_wol;
}
return NULL;
}
static int og_cmd_wol(json_t *element, struct og_msg_params *params)
{
char ips_str[(OG_DB_IP_MAXLEN + 1) * OG_CLIENTS_MAX + 1] = {};
struct og_msg_params new_params = {};
struct og_client_wol *cli_wol;
struct in_addr addr, netmask;
int ips_str_len = 0;
const char *msglog;
struct og_dbi *dbi;
int err = 0, i = 0;
dbi_result result;
const char *key;
json_t *value;
int sd;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "type")) {
err = og_json_parse_type(value, params);
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_WOL_TYPE))
return -1;
for (i = 0; i < params->ips_array_len; ++i) {
ips_str_len += snprintf(ips_str + ips_str_len,
sizeof(ips_str) - ips_str_len,
"'%s',", params->ips_array[i]);
}
ips_str[ips_str_len - 1] = '\0';
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT ordenadores.ip, ordenadores.mac, "
"aulas.netmask "
"FROM ordenadores "
"INNER JOIN aulas "
"ON ordenadores.idaula = aulas.idaula "
"WHERE ordenadores.ip IN (%s)",
ips_str);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
for (i = 0; dbi_result_next_row(result); i++) {
if (i >= OG_CLIENTS_MAX) {
syslog(LOG_ERR, "too many IPs in WoL (%s:%d)\n",
__func__, __LINE__);
dbi_result_free(result);
og_dbi_close(dbi);
goto err_free_params;
}
new_params.ips_array[i] = dbi_result_get_string_copy(result, "ip");
new_params.mac_array[i] = dbi_result_get_string_copy(result, "mac");
new_params.netmask_array[i] = dbi_result_get_string_copy(result, "netmask");
}
new_params.ips_array_len = i;
dbi_result_free(result);
og_dbi_close(dbi);
if (i == 0)
return 0;
sd = wol_socket_open();
if (sd < 0) {
syslog(LOG_ERR, "cannot open wol socket (%s:%d)\n",
__func__, __LINE__);
goto err_free_params;
}
for (i = 0; i < new_params.ips_array_len; i++) {
if (og_client_find(new_params.ips_array[i]))
continue;
if (inet_aton(new_params.ips_array[i], &addr) < 0)
continue;
cli_wol = og_client_wol_find(&addr);
if (cli_wol) {
og_client_wol_refresh(cli_wol);
continue;
}
cli_wol = og_client_wol_create(&addr);
if (!cli_wol)
goto err_out;
list_add_tail(&cli_wol->list, &client_wol_list);
if (inet_aton(new_params.netmask_array[i], &netmask) < 0)
continue;
if (wake_up(sd, &addr, &netmask, new_params.mac_array[i],
atoi(params->wol_type)) < 0) {
syslog(LOG_ERR, "Failed to send wol packet to %s\n",
new_params.ips_array[i]);
continue;
}
}
err_out:
close(sd);
err_free_params:
for (i = 0; i < new_params.ips_array_len; ++i) {
free((void *)new_params.ips_array[i]);
free((void *)new_params.mac_array[i]);
free((void *)new_params.netmask_array[i]);
}
return 0;
}
static int og_json_parse_run(json_t *element, struct og_msg_params *params)
{
if (json_typeof(element) != JSON_STRING)
return -1;
snprintf(params->run_cmd, sizeof(params->run_cmd), "%s",
json_string_value(element));
params->flags |= OG_REST_PARAM_RUN_CMD;
return 0;
}
static int og_cmd_run_post(json_t *element, struct og_msg_params *params)
{
json_t *value, *clients;
const char *key;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
else if (!strcmp(key, "run"))
err = og_json_parse_run(value, params);
else if (!strcmp(key, "echo")) {
err = og_json_parse_bool(value, &params->echo);
params->flags |= OG_REST_PARAM_ECHO;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_RUN_CMD |
OG_REST_PARAM_ECHO))
return -1;
clients = json_copy(element);
json_object_del(clients, "clients");
return og_send_request(OG_METHOD_POST, OG_CMD_SHELL_RUN, params, clients);
}
static int og_cmd_run_get(json_t *element, struct og_msg_params *params,
char *buffer_reply)
{
struct og_buffer og_buffer = {
.data = buffer_reply,
};
json_t *root, *value, *array;
const char *key;
unsigned int i;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
array = json_array();
if (!array)
return -1;
for (i = 0; i < params->ips_array_len; i++) {
json_t *object, *output, *addr, *cmd;
struct og_client *cli;
cli = og_client_find(params->ips_array[i]);
if (!cli || !cli->shell.tstamp)
continue;
object = json_object();
if (!object) {
json_decref(array);
return -1;
}
addr = json_string(params->ips_array[i]);
if (!addr) {
json_decref(object);
json_decref(array);
return -1;
}
json_object_set_new(object, "addr", addr);
cmd = json_string(cli->shell.cmd);
if (!cmd) {
json_decref(object);
json_decref(array);
return -1;
}
json_object_set_new(object, "cmd", cmd);
output = json_string(cli->shell.output);
if (!output) {
json_decref(object);
json_decref(array);
return -1;
}
json_object_set_new(object, "output", output);
json_object_set_new(object, "retcode", json_integer(cli->shell.retcode));
json_object_set_new(object, "tstamp", json_integer(cli->shell.tstamp));
json_array_append_new(array, object);
}
root = json_pack("{s:o}", "clients", array);
if (!root)
return -1;
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
#define OG_SCRIPT_PATH "/opt/opengnsys/client/shell"
struct script_entry {
char name[FILENAME_MAX];
struct list_head list;
};
static void og_script_list_free(struct list_head *script_list)
{
struct script_entry *script, *tmp;
list_for_each_entry_safe(script, tmp, script_list, list) {
list_del(&script->list);
free(script);
}
}
static int og_get_client_scripts(struct list_head *script_list)
{
struct script_entry *script;
struct dirent *dent;
struct stat st;
DIR *d;
if (stat(OG_SCRIPT_PATH, &st) < 0 && errno == ENOENT)
mkdir(OG_SCRIPT_PATH, 0755);
d = opendir(OG_SCRIPT_PATH);
if (!d) {
syslog(LOG_ERR, "Cannot open directory %s (%s:%d)\n",
OG_SCRIPT_PATH, __func__, __LINE__);
return -1;
}
dent = readdir(d);
while (dent) {
if (dent->d_type != DT_REG) {
dent = readdir(d);
continue;
}
script = calloc(1, sizeof(struct script_entry));
if (!script) {
closedir(d);
og_script_list_free(script_list);
return -1;
}
snprintf(script->name, FILENAME_MAX, "%s", dent->d_name);
list_add_tail(&script->list, script_list);
dent = readdir(d);
}
closedir(d);
return 0;
}
static int og_cmd_shell_list(char *buffer_reply)
{
struct og_buffer og_buffer = {
.data = buffer_reply
};
struct script_entry *entry;
json_t *root, *script_arr;
LIST_HEAD(script_list);
if (og_get_client_scripts(&script_list) < 0)
return -1;
root = json_object();
if (!root) {
og_script_list_free(&script_list);
return -1;
}
script_arr = json_array();
if (!script_arr) {
og_script_list_free(&script_list);
json_decref(root);
return -1;
}
list_for_each_entry(entry, &script_list, list)
json_array_append_new(script_arr, json_string(entry->name));
json_object_set_new(root, "scripts", script_arr);
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
og_script_list_free(&script_list);
json_decref(root);
return -1;
}
og_script_list_free(&script_list);
json_decref(root);
return 0;
}
static int og_cmd_session(json_t *element, struct og_msg_params *params)
{
json_t *clients, *value;
const char *key;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "disk")) {
err = og_json_parse_string(value, &params->disk);
params->flags |= OG_REST_PARAM_DISK;
} else if (!strcmp(key, "partition")) {
err = og_json_parse_string(value, &params->partition);
params->flags |= OG_REST_PARAM_PARTITION;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_DISK |
OG_REST_PARAM_PARTITION))
return -1;
clients = json_copy(element);
json_object_del(clients, "clients");
return og_send_request(OG_METHOD_POST, OG_CMD_SESSION, params, clients);
}
static int og_json_os_array_get(struct og_dbi *dbi, json_t *array, const char *ip)
{
unsigned int disk, partition;
const char *os_name;
const char *msglog;
dbi_result result;
json_t *item;
result = dbi_conn_queryf(dbi->conn,
"SELECT op.numdisk, op.numpar, nom.nombreso "
"FROM ordenadores o "
"INNER JOIN ordenadores_particiones op "
" ON o.idordenador = op.idordenador "
"INNER JOIN nombresos nom "
" ON op.idnombreso = nom.idnombreso "
"WHERE o.ip = '%s'", ip);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
item = json_object();
if (!item) {
dbi_result_free(result);
return -1;
}
disk = dbi_result_get_uint(result, "numdisk");
partition = dbi_result_get_uint(result, "numpar");
os_name = dbi_result_get_string(result, "nombreso");
json_object_set_new(item, "disk", json_integer(disk));
json_object_set_new(item, "partition", json_integer(partition));
json_object_set_new(item, "name", json_string(os_name));
json_array_append_new(array, item);
}
dbi_result_free(result);
return 0;
}
static int og_cmd_get_session(json_t *element, struct og_msg_params *params,
char *buffer_reply)
{
json_t *value, *root, *array;
struct og_dbi *dbi;
const char *key;
int err = 0, i;
struct og_buffer og_buffer = {
.data = buffer_reply
};
json_object_foreach(element, key, value) {
if (!strcmp(key, "client")) /* alias for backward compatibility */
err = og_json_parse_clients(value, params);
else if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
else
err = -1;
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
array = json_array();
if (!array) {
og_dbi_close(dbi);
return -1;
}
for (i = 0; i < params->ips_array_len; i++) {
if (og_json_os_array_get(dbi, array, params->ips_array[i]) < 0) {
json_decref(array);
og_dbi_close(dbi);
return -1;
}
}
og_dbi_close(dbi);
root = json_object();
if (!root){
json_decref(array);
return -1;
}
json_object_set_new(root, "sessions", array);
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
static int og_cmd_poweroff(json_t *element, struct og_msg_params *params)
{
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
return og_send_request(OG_METHOD_POST, OG_CMD_POWEROFF, params, NULL);
}
static int og_cmd_refresh(json_t *element, struct og_msg_params *params)
{
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
return og_send_request(OG_METHOD_GET, OG_CMD_REFRESH, params, NULL);
}
static int og_cmd_reboot(json_t *element, struct og_msg_params *params)
{
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
return og_send_request(OG_METHOD_POST, OG_CMD_REBOOT, params, NULL);
}
#define OG_TFTP_TMPL_PATH_UEFI "/opt/opengnsys/tftpboot/grub/templates"
#define OG_TFTP_TMPL_PATH "/opt/opengnsys/tftpboot/menu.lst/templates"
struct og_boot_mode {
struct list_head list;
char name[FILENAME_MAX];
};
static void og_boot_mode_free(struct list_head *boot_mode_list)
{
struct og_boot_mode *mode, *tmp;
list_for_each_entry_safe(mode, tmp, boot_mode_list, list) {
list_del(&mode->list);
free(mode);
}
}
static int og_get_boot_modes(struct list_head *boot_mode_list)
{
struct og_boot_mode *mode;
struct dirent *dent;
DIR *d;
d = opendir(OG_TFTP_TMPL_PATH);
if (!d) {
syslog(LOG_ERR, "Cannot open directory %s (%s:%d)\n",
OG_TFTP_TMPL_PATH, __func__, __LINE__);
return -1;
}
dent = readdir(d);
while (dent) {
if (dent->d_type != DT_REG) {
dent = readdir(d);
continue;
}
mode = calloc(1, sizeof(struct og_boot_mode));
if (!mode) {
closedir(d);
og_boot_mode_free(boot_mode_list);
return -1;
}
snprintf(mode->name, FILENAME_MAX, "%s", dent->d_name);
list_add_tail(&mode->list, boot_mode_list);
dent = readdir(d);
}
closedir(d);
return 0;
}
static int og_cmd_get_modes(json_t *element, struct og_msg_params *params,
char *buffer_reply)
{
struct og_buffer og_buffer = {
.data = buffer_reply
};
struct og_boot_mode *mode;
LIST_HEAD(boot_mode_list);
json_t *root, *modes;
int ret;
root = json_object();
if (!root)
return -1;
modes = json_array();
if (!modes) {
json_decref(root);
return -1;
}
if (og_get_boot_modes(&boot_mode_list) < 0) {
json_decref(modes);
json_decref(root);
return -1;
}
list_for_each_entry(mode, &boot_mode_list, list)
json_array_append_new(modes, json_string(mode->name));
og_boot_mode_free(&boot_mode_list);
json_object_set_new(root, "modes", modes);
ret = json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII);
json_decref(root);
return ret;
}
static int og_change_db_mode(struct og_dbi *dbi, const char *mac,
const char * mode)
{
const char *msglog;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"UPDATE ordenadores SET arranque='%s' "
"WHERE mac='%s'",
mode, mac);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
static bool og_boot_mode_is_valid(const char *name)
{
struct og_boot_mode *mode;
LIST_HEAD(boot_mode_list);
bool found = false;
if (og_get_boot_modes(&boot_mode_list) < 0) {
syslog(LOG_ERR, "failed to get boot mode list (%s:%d)\n",
__FILE__, __LINE__);
return false;
}
list_for_each_entry(mode, &boot_mode_list, list) {
if (!strncmp(name, mode->name, FILENAME_MAX)) {
found = true;
break;
}
}
og_boot_mode_free(&boot_mode_list);
return found;
}
enum {
OG_TFTP_BOOT_BIOS,
OG_TFTP_BOOT_UEFI,
PXE_BOOT_TYPE_MAX,
};
const char *pxe_boot_type_to_dir[] = {
[OG_TFTP_BOOT_BIOS] = "/opt/opengnsys/tftpboot/menu.lst",
[OG_TFTP_BOOT_UEFI] = "/opt/opengnsys/tftpboot/grub"
};
static const char *pxe_boot_type(const int boot_type)
{
if (boot_type < 0 || boot_type >= PXE_BOOT_TYPE_MAX)
return NULL;
return pxe_boot_type_to_dir[boot_type];
}
static int get_grub_filename(unsigned int boot_type, const char *mac,
char *pxe_filename, size_t pxe_filename_size)
{
const char *fmt;
switch (boot_type) {
case OG_TFTP_BOOT_BIOS:
fmt = "01-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c";
break;
case OG_TFTP_BOOT_UEFI:
fmt = "01-%c%c:%c%c:%c%c:%c%c:%c%c:%c%c";
break;
default:
syslog(LOG_ERR, "unknown boot type %d", boot_type);
return -1;
}
snprintf(pxe_filename, pxe_filename_size, fmt,
mac[0], mac[1],
mac[2], mac[3],
mac[4], mac[5],
mac[6], mac[7],
mac[8], mac[9],
mac[10], mac[11]);
switch (boot_type) {
case OG_TFTP_BOOT_BIOS:
str_toupper(pxe_filename);
break;
case OG_TFTP_BOOT_UEFI:
str_tolower(pxe_filename);
break;
default:
syslog(LOG_ERR, "unknown boot type %d", boot_type);
return -1;
}
return 0;
}
static int get_grub_file_path(unsigned int boot_type, const char *mac,
char *pxe_path, size_t pxe_path_size)
{
char pxe_filename[PATH_MAX + 1];
const char *pxe_dir;
int ret;
pxe_dir = pxe_boot_type(boot_type);
if (!pxe_dir) {
syslog(LOG_ERR, "Invalid boot type parameter (%s:%d)\n",
__func__, __LINE__);
return -1;
}
ret = get_grub_filename(boot_type, mac, pxe_filename, sizeof(pxe_filename));
if (ret < 0)
return -1;
ret = snprintf(pxe_path, pxe_path_size,
"%s/%s", pxe_dir, pxe_filename);
if (ret >= pxe_path_size) {
syslog(LOG_ERR, "failed to generate pxe file path (%s:%d)\n",
__func__, __LINE__);
return -1;
}
return 0;
}
static int og_remove_tftpboot_file(unsigned int boot_type, const char *mac)
{
char pxe_file_path[PATH_MAX + 1];
int ret;
ret = get_grub_file_path(boot_type, mac, pxe_file_path, sizeof(pxe_file_path));
if (ret < 0)
return -1;
if (unlink(pxe_file_path) < 0) {
syslog(LOG_ERR, "failed to delete file (%s:%d) %s\n",
__func__, __LINE__, pxe_file_path);
return -1;
}
return 0;
}
static int og_remove_tftpboot_files(struct og_dbi *dbi, const char *ip)
{
const char *msglog, *old_mac;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"SELECT mac FROM ordenadores WHERE ip='%s'", ip);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_next_row(result)) {
old_mac = dbi_result_get_string(result, "mac");
og_remove_tftpboot_file(OG_TFTP_BOOT_BIOS, old_mac);
og_remove_tftpboot_file(OG_TFTP_BOOT_UEFI, old_mac);
}
dbi_result_free(result);
return 0;
}
static int og_create_boot_file(unsigned int boot_type, const char *mac,
const char *mode, char *params)
{
char tmp_filename[] = "/tmp/mode_params_XXXXXX";
char pxe_template_path[PATH_MAX + 1];
char pxe_file_path[PATH_MAX + 1];
char cmd_params[16384] = {};
const char *pxe_dir;
int status;
pid_t pid;
int ret;
int fd;
pxe_dir = pxe_boot_type(boot_type);
if (!pxe_dir) {
syslog(LOG_ERR, "Invalid boot type parameter (%s:%d)\n",
__func__, __LINE__);
return -1;
}
snprintf(pxe_template_path, sizeof(pxe_template_path),
"%s/templates/%s", pxe_dir, mode);
ret = get_grub_file_path(boot_type, mac, pxe_file_path, sizeof(pxe_file_path));
if (ret < 0)
return -1;
if (unlink(pxe_file_path) < 0)
syslog(LOG_INFO, "failed to delete file %s (%s:%d)\n",
pxe_file_path, __func__, __LINE__);
snprintf(cmd_params, sizeof(cmd_params),
"DATA='%s'\nTEMPLATE_PATH='%s'\nPXEFILE_PATH='%s'",
params, pxe_template_path, pxe_file_path);
fd = mkstemp(tmp_filename);
if (fd < 0) {
syslog(LOG_ERR, "cannot generate temp file %s: %s (%s:%d)\n",
tmp_filename, strerror(errno), __func__, __LINE__);
return -1;
}
ret = write(fd, cmd_params, strlen(cmd_params) + 1);
close(fd);
if (ret < 0) {
syslog(LOG_ERR, "cannot write file %s: %s (%s:%d)\n",
tmp_filename, strerror(errno), __func__, __LINE__);
unlink(tmp_filename);
return -1;
}
pid = fork();
if (pid < 0) {
syslog(LOG_ERR, "fork failed (%s:%d) %s\n",
__func__, __LINE__, strerror(errno));
unlink(tmp_filename);
return -1;
}
if (pid == 0) {
execlp("/bin/bash", "/bin/bash",
"/opt/opengnsys/bin/updategrubprofile", tmp_filename, NULL);
syslog(LOG_ERR, "failed script execution (%s:%d) %s\n",
__func__, __LINE__, strerror(errno));
_exit(-1);
} else if (waitpid(pid, &status, 0) < 0) {
syslog(LOG_ERR, "waitpid failed (%s:%d) %s\n",
__func__, __LINE__, strerror(errno));
unlink(tmp_filename);
return -1;
}
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
syslog(LOG_ERR, "failed script execution %s (%s:%d)\n",
strerror(errno), __func__, __LINE__);
unlink(tmp_filename);
return -1;
}
unlink(tmp_filename);
return 0;
}
static int og_set_client_mode(struct og_dbi *dbi, const char *mac,
const char *mode)
{
char params[4096] = "\0";
const char *msglog;
dbi_result result;
unsigned int i;
if (!og_boot_mode_is_valid(mode)) {
syslog(LOG_ERR, "invalid boot mode in client (%s:%d)\n",
__FILE__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT ' LANG=%s', "
"' ip=', CONCAT_WS(':', ordenadores.ip, (@serverip:=entornos.ipserveradm), 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'), "
"' server=', @serverip, "
"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 ' vga=788' "
"WHEN menus.resolucion <= '999' THEN CONCAT(' vga=', menus.resolucion) "
"WHEN menus.resolucion LIKE '%:%' THEN CONCAT(' video=', menus.resolucion) "
"ELSE ' vga=788' END "
"FROM ordenadores "
"JOIN aulas USING(idaula) "
"JOIN centros USING(idcentro) "
"JOIN entidades USING(identidad) "
"JOIN entornos USING(identorno) "
"LEFT JOIN repositorios USING(idrepositorio) "
"LEFT JOIN perfileshard USING(idperfilhard) "
"LEFT JOIN menus USING(idmenu) "
"WHERE ordenadores.mac='%s'", getenv("LANG"), mac);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows(result) != 1) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__FILE__, __LINE__, msglog);
dbi_result_free(result);
return -1;
}
dbi_result_next_row(result);
for (i = 1; i <= dbi_result_get_numfields(result); ++i)
strncat(params, dbi_result_get_string_idx(result, i),
sizeof(params) - strlen(params) - 1);
dbi_result_free(result);
if (og_create_boot_file(OG_TFTP_BOOT_BIOS, mac, mode, params) < 0) {
syslog(LOG_ERR, "failed to create BIOS boot file (%s:%d)\n", __FILE__, __LINE__);
return -1;
}
if (og_create_boot_file(OG_TFTP_BOOT_UEFI, mac, mode, params) < 0) {
og_remove_tftpboot_file(OG_TFTP_BOOT_BIOS, mac);
syslog(LOG_ERR, "failed to create UEFI boot file (%s:%d)\n", __FILE__, __LINE__);
return -1;
}
if (og_change_db_mode(dbi, mac, mode) < 0) {
syslog(LOG_ERR, "failed to change db mode (%s:%d)\n",
__func__, __LINE__);
return -1;
}
return 0;
}
static int og_cmd_post_modes(json_t *element, struct og_msg_params *params)
{
char ips_str[(OG_DB_IP_MAXLEN + 1) * OG_CLIENTS_MAX + 1] = {};
const char *mode_str, *mac;
int ips_str_len = 0;
struct og_dbi *dbi;
uint64_t flags = 0;
dbi_result result;
const char *key;
json_t *value;
int err = 0;
int i;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "mode")) {
err = og_json_parse_string(value, &mode_str);
flags |= OG_REST_PARAM_MODE;
} else {
err = -1;
}
if (err < 0)
return err;
}
if (!og_flags_validate(flags, OG_REST_PARAM_MODE) ||
!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
for (i = 0; i < params->ips_array_len; ++i) {
ips_str_len += snprintf(ips_str + ips_str_len,
sizeof(ips_str) - ips_str_len,
"'%s',", params->ips_array[i]);
}
ips_str[ips_str_len - 1] = '\0';
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT mac FROM ordenadores "
"WHERE ip IN (%s)", ips_str);
while (dbi_result_next_row(result)) {
mac = dbi_result_get_string(result, "mac");
err = og_set_client_mode(dbi, mac, mode_str);
if (err != 0) {
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
static int og_cmd_get_client_setup(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
json_t *value, *root, *partitions_array, *partition_json;
const char *key, *msglog;
unsigned int len_part;
struct og_dbi *dbi;
dbi_result result;
int err = 0;
struct og_buffer og_buffer = {
.data = buffer_reply
};
struct {
int disk;
int number;
int code;
uint64_t size;
int filesystem;
int format;
int os;
int used_size;
int image;
int software;
} partition;
json_object_foreach(element, key, value) {
if (!strcmp(key, "client")) {
err = og_json_parse_clients(value, params);
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
if (params->ips_array_len != 1)
return -1;
root = json_object();
if (!root)
return -1;
partitions_array = json_array();
if (!partitions_array) {
json_decref(root);
return -1;
}
json_object_set_new(root, "partitions", partitions_array);
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
json_decref(root);
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT numdisk, numpar, codpar, tamano, "
" uso, idsistemafichero, idnombreso, "
" idimagen, idperfilsoft "
"FROM ordenadores_particiones "
"INNER JOIN ordenadores "
"ON ordenadores.idordenador = ordenadores_particiones.idordenador "
"WHERE ordenadores.ip='%s'",
params->ips_array[0]);
if (!result) {
json_decref(root);
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
len_part = 0;
/* partition 0 represents the full disk, hence OG_PARTITION_MAX + 1. */
while (dbi_result_next_row(result) && len_part < OG_PARTITION_MAX + 1) {
partition.disk = dbi_result_get_int(result, "numdisk");
partition.number = dbi_result_get_int(result, "numpar");
partition.code = dbi_result_get_int(result, "codpar");
partition.size = dbi_result_get_longlong(result, "tamano");
partition.used_size = dbi_result_get_int(result, "uso");
partition.filesystem = dbi_result_get_int(result, "idsistemafichero");
partition.os = dbi_result_get_int(result, "idnombreso");
partition.image = dbi_result_get_int(result, "idimagen");
partition.software = dbi_result_get_int(result, "idperfilsoft");
partition_json = json_object();
if (!partition_json) {
json_decref(root);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
json_object_set_new(partition_json, "disk",
json_integer(partition.disk));
json_object_set_new(partition_json, "partition",
json_integer(partition.number));
json_object_set_new(partition_json, "code",
json_integer(partition.code));
json_object_set_new(partition_json, "size",
json_integer(partition.size));
json_object_set_new(partition_json, "used_size",
json_integer(partition.used_size));
json_object_set_new(partition_json, "filesystem",
json_integer(partition.filesystem));
json_object_set_new(partition_json, "os",
json_integer(partition.os));
json_object_set_new(partition_json, "image",
json_integer(partition.image));
json_object_set_new(partition_json, "software",
json_integer(partition.software));
json_array_append_new(partitions_array, partition_json);
++len_part;
}
dbi_result_free(result);
og_dbi_close(dbi);
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
static int og_dbi_update_client_entorno(struct og_dbi *dbi,
const char *mac,
const char *server_id)
{
const char *msglog;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"UPDATE ordenadores SET identorno=%s "
"WHERE mac='%s'",
server_id, mac);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to update client's server (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
static int og_dbi_update_client_repo(struct og_dbi *dbi,
const char *mac,
const char *repo_id)
{
const char *msglog;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"UPDATE ordenadores SET idrepositorio=%s "
"WHERE mac='%s'",
repo_id, mac);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to update client's server (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
static int og_cmd_post_client_repo(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
char ips_str[(OG_DB_IP_MAXLEN + 1) * OG_CLIENTS_MAX + 1] = {};
const char *key, *msglog, *mac;
int ips_str_len = 0;
struct og_dbi *dbi;
dbi_result result;
int err = 0, i;
json_t *value;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "id")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
for (i = 0; i < params->ips_array_len; ++i) {
ips_str_len += snprintf(ips_str + ips_str_len,
sizeof(ips_str) - ips_str_len,
"'%s',", params->ips_array[i]);
}
ips_str[ips_str_len - 1] = '\0';
result = dbi_conn_queryf(dbi->conn,
"SELECT mac FROM ordenadores "
"WHERE ip IN (%s)", ips_str);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
while (dbi_result_next_row(result)) {
mac = dbi_result_get_string(result, "mac");
err = og_dbi_update_client_repo(dbi, mac, params->id);
if (err != 0) {
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
static int og_cmd_post_client_server(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
char ips_str[(OG_DB_IP_MAXLEN + 1) * OG_CLIENTS_MAX + 1] = {};
const char *key, *msglog, *mac;
int ips_str_len = 0;
struct og_dbi *dbi;
dbi_result result;
int err = 0, i;
json_t *value;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "id")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
for (i = 0; i < params->ips_array_len; ++i) {
ips_str_len += snprintf(ips_str + ips_str_len,
sizeof(ips_str) - ips_str_len,
"'%s',", params->ips_array[i]);
}
ips_str[ips_str_len - 1] = '\0';
result = dbi_conn_queryf(dbi->conn,
"SELECT mac FROM ordenadores "
"WHERE ip IN (%s)", ips_str);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
while (dbi_result_next_row(result)) {
mac = dbi_result_get_string(result, "mac");
err = og_dbi_update_client_entorno(dbi, mac, params->id);
if (err != 0) {
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
static int og_cmd_get_center_info(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
struct og_center center = {};
json_t *value, *root;
struct og_dbi *dbi;
const char *key;
int err = 0;
struct og_buffer og_buffer = {
.data = buffer_reply
};
json_object_foreach(element, key, value) {
if (!strcmp(key, "id")) {
err = og_json_parse_uint(value, &center.id);
params->flags |= OG_REST_PARAM_CENTER;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_CENTER))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
if (og_dbi_get_center_info(dbi, &center)) {
og_dbi_close(dbi);
return -1;
}
og_dbi_close(dbi);
root = json_object();
if (!root)
return -1;
json_object_set_new(root, "comment",
json_string(center.comment));
json_object_set_new(root, "id",
json_integer(center.id));
json_object_set_new(root, "name",
json_string(center.name));
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
static int og_cmd_get_client_info(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
struct og_computer computer = {};
json_t *value, *root;
struct in_addr addr;
struct og_dbi *dbi;
const char *key;
int err = 0;
struct og_buffer og_buffer = {
.data = buffer_reply
};
json_object_foreach(element, key, value) {
if (!strcmp(key, "client")) {
err = og_json_parse_clients(value, params);
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
if (params->ips_array_len != 1)
return -1;
if (inet_aton(params->ips_array[0], &addr) == 0)
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
if (og_dbi_get_computer_info(dbi, &computer, addr)) {
og_dbi_close(dbi);
return -1;
}
og_dbi_close(dbi);
root = json_object();
if (!root)
return -1;
json_object_set_new(root, "serial_number",
json_string(computer.serial_number));
json_object_set_new(root, "hardware_id",
json_integer(computer.hardware_id));
json_object_set_new(root, "server_id", json_integer(computer.server_id));
json_object_set_new(root, "netdriver", json_string(computer.netdriver));
json_object_set_new(root, "maintenance", json_boolean(computer.maintenance));
json_object_set_new(root, "netiface", json_string(computer.netiface));
json_object_set_new(root, "repo_id", json_integer(computer.repo_id));
json_object_set_new(root, "livedir", json_string(computer.livedir));
json_object_set_new(root, "netmask", json_string(computer.netmask));
json_object_set_new(root, "center", json_integer(computer.center));
json_object_set_new(root, "remote", json_boolean(computer.remote));
json_object_set_new(root, "room", json_integer(computer.room));
json_object_set_new(root, "name", json_string(computer.name));
json_object_set_new(root, "boot", json_string(computer.boot));
json_object_set_new(root, "mac", json_string(computer.mac));
json_object_set_new(root, "id", json_integer(computer.id));
json_object_set_new(root, "ip", json_string(computer.ip));
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
static int og_cmd_post_center_update(json_t *element,
struct og_msg_params *params)
{
const char *key, *msglog;
uint32_t center_id;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "name")) {
err = og_json_parse_string(value, &params->name);
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "comment")) {
err = og_json_parse_string(value, &params->comment);
} else if (!strcmp(key, "id")) {
err = og_json_parse_uint(value, &center_id);
params->flags |= OG_REST_PARAM_CENTER;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_CENTER | OG_REST_PARAM_NAME))
return -1;
if (!params->comment)
params->comment = "";
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT idcentro FROM centros WHERE idcentro='%u'",
center_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows(result) == 0) {
syslog(LOG_ERR, "could not find a center with that id: %u\n",
center_id);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"SELECT idcentro FROM centros "
"WHERE nombrecentro='%s' and idcentro<>'%u'",
params->name, center_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_next_row(result)) {
center_id = dbi_result_get_uint(result, "idcentro");
syslog(LOG_ERR, "the center with id %u already has the name: %s\n",
center_id, params->name);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"UPDATE centros"
" SET nombrecentro='%s',"
" comentarios='%s'"
" WHERE idcentro='%u';",
params->name, params->comment, center_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to update center in database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
return 0;
}
static int og_cmd_post_client_update(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
const char *key, *msglog, *client_ip;
struct og_computer computer = {};
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "ip")) {
err = og_json_parse_string_copy(value,
computer.ip,
sizeof(computer.ip));
params->flags |= OG_REST_PARAM_ADDR;
} else if (!strcmp(key, "id")) {
err = og_json_parse_uint(value, &computer.id);
} else if (!strcmp(key, "serial_number")) {
err = og_json_parse_string_copy(value,
computer.serial_number,
sizeof(computer.serial_number));
} else if (!strcmp(key, "netdriver")) {
err = og_json_parse_string_copy(value,
computer.netdriver,
sizeof(computer.netdriver));
} else if (!strcmp(key, "maintenance")) {
err = og_json_parse_bool(value, &computer.maintenance);
} else if (!strcmp(key, "netiface")) {
err = og_json_parse_string_copy(value,
computer.netiface,
sizeof(computer.netiface));
} else if (!strcmp(key, "repo_id")) {
err = og_json_parse_uint(value, &computer.repo_id);
} else if (!strcmp(key, "netmask")) {
err = og_json_parse_string_copy(value,
computer.netmask,
sizeof(computer.netmask));
} else if (!strcmp(key, "remote")) {
err = og_json_parse_bool(value, &computer.remote);
} else if (!strcmp(key, "room")) {
err = og_json_parse_uint(value, &computer.room);
} else if (!strcmp(key, "name")) {
err = og_json_parse_string_copy(value,
computer.name,
sizeof(computer.name));
} else if (!strcmp(key, "boot")) {
err = og_json_parse_string_copy(value,
computer.boot,
sizeof(computer.boot));
} else if (!strcmp(key, "mac")) {
err = og_json_parse_string_copy(value,
computer.mac,
sizeof(computer.mac));
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT ip FROM ordenadores WHERE ip='%s' AND idordenador<>'%u'",
computer.ip, computer.id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "client with IP %s already exist\n",
computer.ip);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"SELECT ip FROM ordenadores WHERE mac='%s' AND idordenador<>'%u'",
computer.mac, computer.id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_next_row(result)) {
client_ip = dbi_result_get_string(result, "ip");
syslog(LOG_ERR, "client with MAC %s already exist in %s\n",
computer.mac, client_ip);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
og_remove_tftpboot_files(dbi, computer.ip);
result = dbi_conn_queryf(dbi->conn,
"UPDATE ordenadores"
" SET numserie='%s',"
" ip='%s',"
" netdriver='%s',"
" maintenance=%u,"
" netiface='%s',"
" idrepositorio=%u,"
" mascara='%s',"
" inremotepc=%u,"
" idaula=%u,"
" nombreordenador='%s',"
" mac='%s',"
" arranque='%s'"
" WHERE idordenador='%u';",
computer.serial_number,
computer.ip,
computer.netdriver, computer.maintenance,
computer.netiface, computer.repo_id,
computer.netmask, computer.remote,
computer.room, computer.name,
computer.mac, computer.boot,
computer.id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to update client in database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
if (og_set_client_mode(dbi, computer.mac, computer.boot)) {
syslog(LOG_ERR, "failed to set client boot mode (%s:%d)\n",
__func__, __LINE__);
og_dbi_close(dbi);
return -1;
}
og_dbi_close(dbi);
return 0;
}
static int add_room_folder(struct og_dbi *dbi, struct og_folder *folder)
{
dbi_result result;
const char *msglog;
result = dbi_conn_queryf(dbi->conn,
"SELECT nombregrupo FROM grupos WHERE nombregrupo='%s'",
folder->name);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "room-folder with that name already exists: %s\n",
folder->name);
dbi_result_free(result);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO grupos("
" nombregrupo,"
" grupoid,"
" tipo,"
" idcentro,"
" iduniversidad"
") VALUES ('%s', 0, 2, %u, 0)",
folder->name, folder->center);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to add room-folder to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
static int add_computer_folder(struct og_dbi *dbi, struct og_folder *folder)
{
dbi_result result;
const char *msglog;
result = dbi_conn_queryf(dbi->conn,
"SELECT nombregrupoordenador FROM gruposordenadores WHERE nombregrupoordenador='%s'",
folder->name);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "computer-folder with that name already exists: %s\n",
folder->name);
dbi_result_free(result);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO gruposordenadores("
" nombregrupoordenador,"
" idaula,"
" grupoid"
") VALUES ('%s', %u, 0)",
folder->name, folder->room);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to add computer-folder to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
static int og_computer_folder_update(struct og_dbi *dbi, struct og_folder *folder)
{
const char *msglog;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"SELECT idaula FROM gruposordenadores WHERE idgrupo='%u'",
folder->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
if (!dbi_result_next_row(result)) {
syslog(LOG_ERR, "could not find a folder with that id: %u\n",
folder->id);
dbi_result_free(result);
return -1;
}
folder->room = dbi_result_get_uint(result, "idaula");
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"SELECT idgrupo FROM gruposordenadores "
"WHERE nombregrupoordenador='%s' AND idaula=%u",
folder->name, folder->room);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "Folder with name %s already exists in room "
"with id %d\n",
folder->name, folder->room);
dbi_result_free(result);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"UPDATE gruposordenadores"
" SET nombregrupoordenador='%s'"
" WHERE idgrupo='%u';",
folder->name, folder->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to update room in database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
static int og_room_folder_update(struct og_dbi *dbi, struct og_folder *folder)
{
const char *msglog;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"SELECT idcentro FROM grupos WHERE idgrupo='%u'",
folder->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
if (!dbi_result_next_row(result)) {
syslog(LOG_ERR, "could not find a folder with that id: %u\n",
folder->id);
dbi_result_free(result);
return -1;
}
folder->center = dbi_result_get_uint(result, "idcentro");
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"SELECT idgrupo FROM grupos "
"WHERE nombregrupo='%s' AND idcentro=%u",
folder->name, folder->center);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "Folder with name %s already exists in center "
"with id %d\n",
folder->name, folder->center);
dbi_result_free(result);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"UPDATE grupos"
" SET nombregrupo='%s'"
" WHERE idgrupo='%u';",
folder->name, folder->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to update room in database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
#define OG_COMPUTER_FOLDER_MARKER 0x00010000
static int og_cmd_post_folder_update(json_t *element,
struct og_msg_params *params)
{
struct og_folder folder = {};
struct og_dbi *dbi;
const char *key;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "id")) {
params->flags |= OG_REST_PARAM_FOLDER;
err = og_json_parse_uint(value, &folder.id);
} else if (!strcmp(key, "name")) {
params->flags |= OG_REST_PARAM_NAME;
err = og_json_parse_string_copy(value,
folder.name,
sizeof(folder.name));
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_NAME))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
if (folder.id & OG_COMPUTER_FOLDER_MARKER) {
folder.id = folder.id & 0x0000ffff;
err = og_computer_folder_update(dbi, &folder);
} else {
err = og_room_folder_update(dbi, &folder);
}
og_dbi_close(dbi);
return err;
}
static int og_cmd_post_folder_add(json_t *element,
struct og_msg_params *params)
{
const char *key;
json_t *value;
struct og_folder folder = {};
struct og_dbi *dbi;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "center")) {
params->flags |= OG_REST_PARAM_CENTER;
err = og_json_parse_uint(value, &folder.center);
} else if (!strcmp(key, "room")) {
params->flags |= OG_REST_PARAM_ROOM;
err = og_json_parse_uint(value, &folder.room);
} else if (!strcmp(key, "name")) {
params->flags |= OG_REST_PARAM_NAME;
err = og_json_parse_string_copy(value,
folder.name,
sizeof(folder.name));
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_NAME))
return -1;
if (og_msg_params_validate(params, OG_REST_PARAM_ROOM | OG_REST_PARAM_CENTER))
return -1;
if (!og_msg_params_validate(params, OG_REST_PARAM_ROOM) && !og_msg_params_validate(params, OG_REST_PARAM_CENTER))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
if (params->flags & OG_REST_PARAM_ROOM)
err = add_computer_folder(dbi, &folder);
else if (params->flags & OG_REST_PARAM_CENTER)
err = add_room_folder(dbi, &folder);
else
err = -1;
og_dbi_close(dbi);
return err;
}
static int og_delete_computer_folder(struct og_dbi *dbi, uint32_t folder_id)
{
const char *msglog;
dbi_result result;
folder_id = folder_id & 0x0000ffff;
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM gruposordenadores "
"WHERE idgrupo=%u",
folder_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to delete computer-group from database "
"(%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
if (dbi_result_get_numrows_affected(result) < 1) {
syslog(LOG_ERR, "delete did not modify any row (%s:%d)\n",
__func__, __LINE__);
dbi_result_free(result);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM ordenadores "
"WHERE grupoid=%u",
folder_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to delete computers from database "
"(%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
static int og_delete_room_folder(struct og_dbi *dbi, uint32_t folder_id)
{
const char *msglog;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM grupos "
"WHERE idgrupo=%u",
folder_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to delete room-group from database "
"(%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
if (dbi_result_get_numrows_affected(result) < 1) {
syslog(LOG_ERR, "delete did not modify any row (%s:%d)\n",
__func__, __LINE__);
dbi_result_free(result);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM aulas "
"WHERE grupoid=%u",
folder_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to delete rooms from database "
"(%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
static int og_cmd_post_folder_delete(json_t *element,
struct og_msg_params *params)
{
struct og_dbi *dbi;
uint32_t folder_id;
const char *key;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "id")) {
err = og_json_parse_uint(value, &folder_id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
if (folder_id & 0x00010000) {
err = og_delete_computer_folder(dbi, folder_id);
} else {
err = og_delete_room_folder(dbi, folder_id);
}
og_dbi_close(dbi);
return err;
}
static int og_cmd_post_client_add(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
const char *room_name, *computer_name, *computer_ip, *hwaddr;
struct og_computer computer = {};
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "serial_number")) {
err = og_json_parse_string_copy(value,
computer.serial_number,
sizeof(computer.serial_number));
} else if (!strcmp(key, "hardware_id")) {
err = og_json_parse_uint(value, &computer.hardware_id);
} else if (!strcmp(key, "folder_id")) {
err = og_json_parse_uint(value, &computer.folder_id);
if (!err)
computer.folder_id = computer.folder_id & 0x0000ffff;
} else if (!strcmp(key, "netdriver")) {
err = og_json_parse_string_copy(value,
computer.netdriver,
sizeof(computer.netdriver));
} else if (!strcmp(key, "maintenance")) {
err = og_json_parse_bool(value, &computer.maintenance);
} else if (!strcmp(key, "netiface")) {
err = og_json_parse_string_copy(value,
computer.netiface,
sizeof(computer.netiface));
} else if (!strcmp(key, "repo_id")) {
err = og_json_parse_uint(value, &computer.repo_id);
} else if (!strcmp(key, "livedir")) {
err = og_json_parse_string_copy(value,
computer.livedir,
sizeof(computer.livedir));
} else if (!strcmp(key, "netmask")) {
err = og_json_parse_string_copy(value,
computer.netmask,
sizeof(computer.netmask));
} else if (!strcmp(key, "remote")) {
err = og_json_parse_bool(value, &computer.remote);
} else if (!strcmp(key, "room")) {
err = og_json_parse_uint(value, &computer.room);
} else if (!strcmp(key, "name")) {
err = og_json_parse_string_copy(value,
computer.name,
sizeof(computer.name));
} else if (!strcmp(key, "boot")) {
err = og_json_parse_string_copy(value,
computer.boot,
sizeof(computer.boot));
} else if (!strcmp(key, "mac")) {
err = og_json_parse_string_copy(value,
computer.mac,
sizeof(computer.mac));
} else if (!strcmp(key, "ip")) {
err = og_json_parse_string_copy(value,
computer.ip,
sizeof(computer.ip));
}
if (err < 0)
return err;
}
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT ip FROM ordenadores WHERE ip='%s'",
computer.ip);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "client with the same IP already exists: %s\n",
computer.ip);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"SELECT nombreordenador, ip, nombreaula"
" FROM ordenadores"
" INNER JOIN aulas on ordenadores.idaula = aulas.idaula"
" WHERE mac='%s'",
computer.mac);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_next_row(result)) {
room_name = dbi_result_get_string(result, "nombreaula");
computer_name = dbi_result_get_string(result, "nombreordenador");
computer_ip = dbi_result_get_string(result, "ip");
hwaddr = dbi_result_get_string(result, "mac");
syslog(LOG_ERR, "Failed to add client %s because %s (%s) in room %s already owns MAC address %s\n",
computer.ip, computer_ip, computer_name, room_name, hwaddr);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO ordenadores("
" nombreordenador,"
" numserie,"
" ip,"
" mac,"
" idaula,"
" grupoid,"
" idperfilhard,"
" idrepositorio,"
" mascara,"
" arranque,"
" netiface,"
" netdriver,"
" oglivedir,"
" inremotepc,"
" maintenance"
") VALUES ('%s', '%s', '%s', '%s', %u, %u, %u,"
" %u, '%s', '%s', '%s', '%s',"
" '%s', %u, %u)",
computer.name, computer.serial_number,
computer.ip, computer.mac, computer.room,
computer.folder_id, computer.hardware_id,
computer.repo_id, computer.netmask,
computer.boot, computer.netiface,
computer.netdriver, computer.livedir,
computer.remote, computer.maintenance);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to add client to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
if (og_set_client_mode(dbi, computer.mac, computer.boot)) {
syslog(LOG_ERR, "failed to set client boot mode (%s:%d)\n",
__func__, __LINE__);
og_dbi_close(dbi);
return -1;
}
og_dbi_close(dbi);
return 0;
}
static int og_cmd_post_client_delete(json_t *element,
struct og_msg_params *params)
{
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
unsigned int i;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
for (i = 0; i < params->ips_array_len; i++) {
og_remove_tftpboot_files(dbi, params->ips_array[i]);
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM ordenadores WHERE ip='%s'",
params->ips_array[i]);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows_affected(result) < 1) {
syslog(LOG_ERR, "delete did not modify any row (%s:%d)\n",
__func__, __LINE__);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
}
og_dbi_close(dbi);
return 0;
}
static int og_cmd_post_client_move(json_t *element,
struct og_msg_params *params)
{
struct og_computer computer = {};
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
unsigned int i;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "room")) {
err = og_json_parse_uint(value, &computer.room);
} else if (!strcmp(key, "folder_id")) {
err = og_json_parse_uint(value, &computer.folder_id);
if (!err)
computer.folder_id = computer.folder_id & 0x0000ffff;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
for (i = 0; i < params->ips_array_len; i++) {
result = dbi_conn_queryf(dbi->conn,
"UPDATE ordenadores SET "
"idaula=%u, grupoid=%u WHERE ip='%s'",
computer.room, computer.folder_id,
params->ips_array[i]);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows_affected(result) < 1) {
syslog(LOG_ERR, "client move did not modify any row (%s:%d)\n",
__func__, __LINE__);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
}
og_dbi_close(dbi);
return 0;
}
static int og_cmd_get_room_info(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
struct og_room room = {};
json_t *value, *root;
struct og_dbi *dbi;
uint32_t room_id;
const char *key;
int err = 0;
struct og_buffer og_buffer = {
.data = buffer_reply
};
json_object_foreach(element, key, value) {
if (!strcmp(key, "id")) {
err = og_json_parse_uint(value, &room_id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
if (og_dbi_get_room_info(dbi, &room, room_id)) {
og_dbi_close(dbi);
return -1;
}
og_dbi_close(dbi);
root = json_object();
if (!root)
return -1;
json_object_set_new(root, "id", json_integer(room.id));
json_object_set_new(root, "name", json_string(room.name));
json_object_set_new(root, "gateway", json_string(room.gateway));
json_object_set_new(root, "netmask", json_string(room.netmask));
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
static int og_cmd_stop(json_t *element, struct og_msg_params *params)
{
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
return og_send_request(OG_METHOD_POST, OG_CMD_STOP, params, NULL);
}
static int og_cmd_hardware(json_t *element, struct og_msg_params *params)
{
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
return og_send_request(OG_METHOD_GET, OG_CMD_HARDWARE, params, NULL);
}
static int og_cmd_get_hardware(json_t *element, struct og_msg_params *params,
char *buffer_reply)
{
const char *key, *msglog, *hw_item, *hw_type;
json_t *value, *root, *array, *item;
struct og_dbi *dbi;
dbi_result result;
int err = 0;
struct og_buffer og_buffer = {
.data = buffer_reply
};
json_object_foreach(element, key, value) {
if (!strcmp(key, "client"))
err = og_json_parse_clients(value, params);
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT hardwares.descripcion AS item, "
" tipohardwares.descripcion AS type "
"FROM hardwares "
"INNER JOIN perfileshard_hardwares "
" ON hardwares.idhardware = perfileshard_hardwares.idhardware "
"INNER JOIN ordenadores "
" ON perfileshard_hardwares.idperfilhard = ordenadores.idperfilhard "
"INNER JOIN tipohardwares "
" ON hardwares.idtipohardware = tipohardwares.idtipohardware "
"WHERE ordenadores.ip = '%s'",
params->ips_array[0]);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
array = json_array();
if (!array) {
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
while (dbi_result_next_row(result)) {
item = json_object();
if (!item) {
dbi_result_free(result);
og_dbi_close(dbi);
json_decref(array);
return -1;
}
hw_item = dbi_result_get_string(result, "item");
hw_type = dbi_result_get_string(result, "type");
json_object_set_new(item, "type", json_string(hw_type));
json_object_set_new(item, "description", json_string(hw_item));
json_array_append_new(array, item);
}
dbi_result_free(result);
og_dbi_close(dbi);
root = json_object();
if (!root){
json_decref(array);
return -1;
}
json_object_set_new(root, "hardware", array);
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
static int og_cmd_software(json_t *element, struct og_msg_params *params)
{
json_t *clients, *value;
const char *key;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
else if (!strcmp(key, "disk")) {
err = og_json_parse_string(value, &params->disk);
params->flags |= OG_REST_PARAM_DISK;
}
else if (!strcmp(key, "partition")) {
err = og_json_parse_string(value, &params->partition);
params->flags |= OG_REST_PARAM_PARTITION;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_DISK |
OG_REST_PARAM_PARTITION))
return -1;
clients = json_copy(element);
json_object_del(clients, "clients");
return og_send_request(OG_METHOD_GET, OG_CMD_SOFTWARE, params, clients);
}
static int og_cmd_get_software(json_t *element, struct og_msg_params *params,
char *buffer_reply)
{
json_t *value, *software, *root;
const char *key, *msglog, *name;
uint64_t disk, partition;
uint64_t flags = 0;
struct og_dbi *dbi;
dbi_result result;
int err = 0;
struct og_buffer og_buffer = {
.data = buffer_reply
};
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "client")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "disk")) {
err = og_json_parse_uint64(value, &disk);
flags |= OG_REST_PARAM_DISK;
} else if (!strcmp(key, "partition")) {
err = og_json_parse_uint64(value, &partition);
flags |= OG_REST_PARAM_PARTITION;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR) ||
!og_flags_validate(flags, OG_REST_PARAM_DISK |
OG_REST_PARAM_PARTITION))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT s.descripcion "
"FROM softwares s "
"INNER JOIN perfilessoft_softwares pss "
"ON s.idsoftware = pss.idsoftware "
"INNER JOIN ordenadores_particiones op "
"ON pss.idperfilsoft = op.idperfilsoft "
"INNER JOIN ordenadores o "
"ON o.idordenador = op.idordenador "
"WHERE o.ip='%s' AND "
" op.numdisk=%lu AND "
" op.numpar=%lu",
params->ips_array[0], disk, partition);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
software = json_array();
if (!software) {
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
while (dbi_result_next_row(result)) {
name = dbi_result_get_string(result, "descripcion");
json_array_append_new(software, json_string(name));
}
dbi_result_free(result);
og_dbi_close(dbi);
root = json_object();
if (!root) {
json_decref(software);
return -1;
}
json_object_set_new(root, "software", software);
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
static const int og_cmd_get_repositories(char *buffer_reply)
{
json_t *root, *repositories, *repository, *id, *ip, *name;
struct og_buffer og_buffer = {
.data = buffer_reply,
};
struct og_dbi *dbi;
dbi_result result;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT idrepositorio, ip, nombrerepositorio "
"FROM repositorios");
repositories = json_array();
while (dbi_result_next_row(result)) {
repository = json_object();
id = json_integer(dbi_result_get_ulonglong(result,
"idrepositorio"));
ip = json_string(dbi_result_get_string(result, "ip"));
name = json_string(dbi_result_get_string(result,
"nombrerepositorio"));
json_object_set_new(repository, "id", id);
json_object_set_new(repository, "ip", ip);
json_object_set_new(repository, "name", name);
json_array_append_new(repositories, repository);
}
dbi_result_free(result);
og_dbi_close(dbi);
root = json_object();
json_object_set_new(root, "repositories", repositories);
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
#define OG_IMAGE_TYPE_MAXLEN 4
static json_t *og_json_disk_alloc()
{
const char *dir = ogconfig.repo.dir;
struct statvfs buffer;
json_t *disk_json;
int ret;
ret = statvfs(dir, &buffer);
if (ret)
return NULL;
disk_json = json_object();
if (!disk_json)
return NULL;
json_object_set_new(disk_json, "total",
json_integer(buffer.f_blocks * buffer.f_frsize));
json_object_set_new(disk_json, "free",
json_integer(buffer.f_bfree * buffer.f_frsize));
return disk_json;
}
#define OG_PERMS_IRWX (S_IRWXU | S_IRWXG | S_IRWXO)
#define OG_PERMS_MAXLEN 4
static json_t *og_json_image_alloc(struct og_image *image)
{
char perms_string[OG_PERMS_MAXLEN];
json_t *image_json;
char *modified;
image_json = json_object();
if (!image_json)
return NULL;
snprintf(perms_string, sizeof(perms_string), "%o", image->perms);
modified = ctime(&image->lastupdate);
modified[strlen(modified) - 1] = '\0';
json_object_set_new(image_json, "name",
json_string(image->name));
json_object_set_new(image_json, "datasize",
json_integer(image->datasize));
json_object_set_new(image_json, "size",
json_integer(image->size));
json_object_set_new(image_json, "modified",
json_string(modified));
json_object_set_new(image_json, "permissions",
json_string(perms_string));
json_object_set_new(image_json, "software_id",
json_integer(image->software_id));
json_object_set_new(image_json, "type",
json_integer(image->type));
json_object_set_new(image_json, "id",
json_integer(image->id));
json_object_set_new(image_json, "repo_id",
json_integer(image->repo_id));
json_object_set_new(image_json, "description",
json_string(image->description));
json_object_set_new(image_json, "checksum",
json_string(image->checksum));
return image_json;
}
static int og_cmd_images(char *buffer_reply)
{
json_t *root, *images, *image_json, *disk_json;
struct og_buffer og_buffer = {
.data = buffer_reply
};
struct og_image image;
struct og_dbi *dbi;
dbi_result result;
root = json_object();
if (!root)
return -1;
images = json_array();
if (!images) {
json_decref(root);
return -1;
}
json_object_set_new(root, "images", images);
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
json_decref(root);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT i.nombreca, o.nombreordenador, "
" i.clonator, i.compressor, "
" i.filesystem, i.datasize, i.size, "
" i.lastupdate, i.permissions, "
" i.idperfilsoft, i.tipo, "
" i.idimagen, i.idrepositorio, "
" i.descripcion, i.checksum "
"FROM imagenes i "
"LEFT JOIN ordenadores o "
"ON i.idordenador = o.idordenador ");
while (dbi_result_next_row(result)) {
image = (struct og_image){0};
image.datasize = dbi_result_get_ulonglong(result, "datasize");
image.size = dbi_result_get_ulonglong(result, "size");
image.lastupdate = dbi_result_get_ulonglong(result, "lastupdate");
image.perms = dbi_result_get_uint(result, "permissions");
image.software_id = dbi_result_get_ulonglong(result, "idperfilsoft");
image.type = dbi_result_get_ulonglong(result, "tipo");
image.id = dbi_result_get_ulonglong(result, "idimagen");
image.repo_id = dbi_result_get_ulonglong(result, "idrepositorio");
snprintf(image.checksum, sizeof(image.checksum), "%s",
dbi_result_get_string(result, "checksum"));
snprintf(image.name, sizeof(image.name), "%s",
dbi_result_get_string(result, "nombreca"));
snprintf(image.description, sizeof(image.description), "%s",
dbi_result_get_string(result, "descripcion"));
snprintf(image.checksum, sizeof(image.checksum), "%s",
dbi_result_get_string(result, "checksum"));
image_json = og_json_image_alloc(&image);
if (!image_json) {
dbi_result_free(result);
og_dbi_close(dbi);
json_decref(root);
return -1;
}
json_array_append_new(images, image_json);
}
dbi_result_free(result);
og_dbi_close(dbi);
disk_json = og_json_disk_alloc();
if (!disk_json) {
syslog(LOG_ERR, "cannot allocate disk json");
json_decref(root);
return -1;
}
json_object_set_new(root, "disk", disk_json);
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
int og_json_parse_create_image(json_t *element,
struct og_msg_params *params)
{
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "disk")) {
err = og_json_parse_string(value, &params->disk);
params->flags |= OG_REST_PARAM_DISK;
} else if (!strcmp(key, "partition")) {
err = og_json_parse_string(value, &params->partition);
params->flags |= OG_REST_PARAM_PARTITION;
} else if (!strcmp(key, "name")) {
err = og_json_parse_string_copy(value,
(char *)&params->image.name,
sizeof(params->image.name));
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "repository_id")) {
err = og_json_parse_uint64(value, &params->image.repo_id);
params->flags |= OG_REST_PARAM_REPO;
} else if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "id")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
} else if (!strcmp(key, "code")) {
err = og_json_parse_string(value, &params->code);
params->flags |= OG_REST_PARAM_CODE;
} else if (!strcmp(key, "description")) {
err = og_json_parse_string_copy(value,
(char *)&params->image.description,
sizeof(params->image.description));
} else if (!strcmp(key, "group_id")) {
err = og_json_parse_uint64(value, &params->image.group_id);
} else if (!strcmp(key, "center_id")) {
err = og_json_parse_uint64(value, &params->image.center_id);
} else if (!strcmp(key, "backup")) {
err = og_json_parse_bool(value, &params->backup);
params->flags |= OG_REST_PARAM_BACKUP;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_BACKUP))
params->backup = true;
return 0;
}
static int og_cmd_add_image(json_t *element, struct og_msg_params *params,
bool update)
{
char repository_ip[OG_DB_IP_MAXLEN + 1];
char new_image_id[OG_DB_INT_MAXLEN + 1];
struct og_dbi *dbi;
json_t *clients;
int err = 0;
bool found;
err = og_json_parse_create_image(element, params);
if (err < 0)
return err;
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_DISK |
OG_REST_PARAM_PARTITION |
OG_REST_PARAM_CODE |
OG_REST_PARAM_ID |
OG_REST_PARAM_NAME))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR,
"cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
found = og_dbi_get_image(dbi, &params->image);
if (!found) {
if (update) {
syslog(LOG_ERR, "cannot update image file `%s', it does not exist\n",
params->image.name);
og_dbi_close(dbi);
return -1;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_REPO)) {
syslog(LOG_ERR,
"missing repo parameter in request (%s:%d)\n",
__func__, __LINE__);
og_dbi_close(dbi);
return -1;
}
err = og_dbi_add_image(dbi, &params->image);
if (err < 0) {
og_dbi_close(dbi);
return err;
}
snprintf(new_image_id, sizeof(new_image_id), "%lu", params->image.id);
params->id = new_image_id;
} else {
syslog(LOG_INFO, "updating existing image `%s'\n", params->image.name);
snprintf(new_image_id, sizeof(new_image_id), "%lu", params->image.id);
params->id = new_image_id;
}
json_object_set_new(element, "id", json_string(params->id));
clients = json_copy(element);
json_object_del(clients, "clients");
err = og_dbi_get_repository_ip(dbi, params->image.repo_id, repository_ip);
og_dbi_close(dbi);
if (err < 0)
return err;
json_object_set_new(clients ,"repository", json_string(repository_ip));
json_object_set_new(clients ,"backup", json_boolean(params->backup));
return og_send_request(OG_METHOD_POST, OG_CMD_IMAGE_CREATE, params,
clients);
}
static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
{
return og_cmd_add_image(element, params, false);
}
static int og_cmd_update_image(json_t *element, struct og_msg_params *params)
{
return og_cmd_add_image(element, params, true);
}
int og_json_parse_restore_image(json_t *element, struct og_msg_params *params)
{
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "disk")) {
err = og_json_parse_string(value, &params->disk);
params->flags |= OG_REST_PARAM_DISK;
} else if (!strcmp(key, "partition")) {
err = og_json_parse_string(value, &params->partition);
params->flags |= OG_REST_PARAM_PARTITION;
} else if (!strcmp(key, "name")) {
err = og_json_parse_string(value, &params->name);
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "repository")) {
err = og_json_parse_string(value, &params->repository);
params->flags |= OG_REST_PARAM_REPO;
} else if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "type")) {
err = og_json_parse_string(value, &params->type);
params->flags |= OG_REST_PARAM_TYPE;
} else if (!strcmp(key, "profile")) {
err = og_json_parse_string(value, &params->profile);
params->flags |= OG_REST_PARAM_PROFILE;
} else if (!strcmp(key, "id")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
return err;
}
return 0;
}
static int og_cmd_restore_image(json_t *element, struct og_msg_params *params)
{
json_t *clients;
int err = 0;
err = og_json_parse_restore_image(element, params);
if (err < 0)
return err;
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_DISK |
OG_REST_PARAM_PARTITION |
OG_REST_PARAM_NAME |
OG_REST_PARAM_REPO |
OG_REST_PARAM_TYPE |
OG_REST_PARAM_PROFILE |
OG_REST_PARAM_ID))
return -1;
clients = json_copy(element);
json_object_del(clients, "clients");
return og_send_request(OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, params,
clients);
}
static int og_delete_image(struct og_dbi *dbi, const uint32_t image_id)
{
char filename[PATH_MAX + 1], checksum[PATH_MAX + 1];
const char *image;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"SELECT nombreca FROM imagenes "
"WHERE idimagen='%u'",
image_id);
if (!result) {
syslog(LOG_ERR, "failed to query database\n");
return -1;
}
if (!dbi_result_next_row(result)) {
dbi_result_free(result);
syslog(LOG_ERR, "image \"%u\" does not exist in database\n", image_id);
return -1;
}
image = dbi_result_get_string(result, "nombreca");
snprintf(filename, sizeof(filename), "%s/%s.img", ogconfig.repo.dir,
image);
snprintf(checksum, sizeof(checksum), "%s/%s.img.full.sum", ogconfig.repo.dir,
image);
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM imagenes "
"WHERE idimagen='%u'",
image_id);
if (!result) {
syslog(LOG_ERR, "failed to query database\n");
return -1;
}
if (dbi_result_get_numrows_affected(result) < 1) {
syslog(LOG_ERR, "delete did not modify any row (%s:%d)\n",
__func__, __LINE__);
dbi_result_free(result);
return -1;
}
dbi_result_free(result);
unlink(filename);
unlink(checksum);
return 0;
}
static int og_cmd_delete_image(json_t *element, struct og_msg_params *params)
{
struct og_dbi *dbi;
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "image")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
err = og_delete_image(dbi, atoi(params->id));
if (err < 0) {
og_dbi_close(dbi);
return err;
}
og_dbi_close(dbi);
return 0;
}
struct og_scope_image {
struct list_head list;
uint32_t id;
};
static void og_scope_image_list_free(struct list_head *scope_list)
{
struct og_scope_image *scope, *next;
list_for_each_entry_safe(scope, next, scope_list, list) {
list_del(&scope->list);
free(scope);
}
}
static int og_json_parse_scope_image_list(json_t *element, struct list_head *scope_list)
{
struct og_scope_image *scope;
unsigned int i;
json_t *k;
if (json_typeof(element) != JSON_ARRAY)
return -1;
for (i = 0; i < json_array_size(element); i++) {
k = json_array_get(element, i);
if (json_typeof(k) != JSON_INTEGER)
goto err_out;
scope = calloc(1, sizeof(struct og_scope_image));
if (!scope)
goto err_out;
scope->id = json_integer_value(k);
list_add_tail(&scope->list, scope_list);
}
return 0;
err_out:
og_scope_image_list_free(scope_list);
return -1;
}
enum {
OG_ATTR_IMAGE_ID = (1 << 0),
OG_ATTR_IMAGE_SCOPE_ID = (1 << 0),
};
static int og_cmd_image_scope_update(json_t *element, struct og_msg_params *params)
{
struct og_scope_image *scope;
LIST_HEAD(scope_list);
struct og_dbi *dbi;
const char *msglog;
uint32_t image_id;
dbi_result result;
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "image")) {
err = og_json_parse_uint(value, &image_id);
params->flags |= OG_ATTR_IMAGE_ID;
} else if (!strcmp(key, "scopes")) {
err = og_json_parse_scope_image_list(value, &scope_list);
if (err >= 0 && !list_empty(&scope_list))
params->flags |= OG_ATTR_IMAGE_SCOPE_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_ATTR_IMAGE_ID |
OG_ATTR_IMAGE_SCOPE_ID)) {
og_scope_image_list_free(&scope_list);
return -1;
}
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
og_scope_image_list_free(&scope_list);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM image_scope WHERE image_id=%d",
image_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
goto err_out;
}
dbi_result_free(result);
list_for_each_entry(scope, &scope_list, list) {
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO image_scope (image_id, scope_id) "
"VALUES (%d, %d)", image_id, scope->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
goto err_out;
}
dbi_result_free(result);
}
og_dbi_close(dbi);
og_scope_image_list_free(&scope_list);
return 0;
err_out:
og_scope_image_list_free(&scope_list);
og_dbi_close(dbi);
return -1;
}
static json_t *og_json_image_scope(struct og_dbi *dbi, uint32_t image_id)
{
json_t *scope_image, *scope_array;
const char *msglog;
uint32_t scope_id;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"SELECT scope_id FROM image_scope WHERE image_id = '%u'", image_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return NULL;
}
scope_image = json_object();
if (!scope_image) {
dbi_result_free(result);
return NULL;
}
json_object_set_new(scope_image, "id", json_integer(image_id));
scope_array = json_array();
if (!scope_array) {
json_decref(scope_image);
dbi_result_free(result);
return NULL;
}
while (dbi_result_next_row(result)) {
scope_id = dbi_result_get_uint(result, "scope_id");
json_array_append_new(scope_array, json_integer(scope_id));
}
dbi_result_free(result);
json_object_set_new(scope_image, "scopes", scope_array);
return scope_image;
}
static int og_cmd_image_scope_list(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
struct og_buffer og_buffer = {
.data = buffer_reply
};
json_t *value, *scope_image;
struct og_dbi *dbi;
uint32_t image_id;
const char *key;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "image")) {
err = og_json_parse_uint(value, &image_id);
params->flags |= OG_ATTR_IMAGE_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_ATTR_IMAGE_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
scope_image = og_json_image_scope(dbi, image_id);
og_dbi_close(dbi);
if (!scope_image)
return -1;
if (json_dump_callback(scope_image, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(scope_image);
return -1;
}
json_decref(scope_image);
return 0;
}
static int og_dbi_client_cache_get(struct og_dbi *dbi, json_t *clients, const char *ip)
{
const char *img_name, *msglog, *img_checksum;
json_t *client_data, *cache_arr, *img_info;
uint64_t img_size, cache_size = 0;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"SELECT ordenadores_particiones.tamano "
"FROM ordenadores_particiones JOIN ordenadores "
"ON ordenadores.idordenador = ordenadores_particiones.idordenador "
"WHERE ordenadores.ip = '%s' AND codpar = 202", ip);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
if (dbi_result_next_row(result)) {
cache_size = dbi_result_get_longlong(result, "tamano") * 1024;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"SELECT cache.imagename, cache.size, cache.checksum "
"FROM ordenadores JOIN cache "
"ON ordenadores.idordenador = cache.clientid "
"WHERE ordenadores.ip = '%s'", ip);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
client_data = json_object();
if (!client_data) {
dbi_result_free(result);
return -1;
}
cache_arr = json_array();
if (!cache_arr) {
json_decref(client_data);
dbi_result_free(result);
return -1;
}
while (dbi_result_next_row(result)) {
img_name = dbi_result_get_string(result, "imagename");
img_size = dbi_result_get_ulonglong(result, "size");
img_checksum = dbi_result_get_string(result, "checksum");
img_info = json_object();
if (!img_info) {
json_decref(client_data);
json_decref(cache_arr);
dbi_result_free(result);
return -1;
}
json_object_set_new(img_info, "name", json_string(img_name));
json_object_set_new(img_info, "size", json_integer(img_size));
json_object_set_new(img_info, "checksum", json_string(img_checksum));
json_array_append_new(cache_arr, img_info);
}
json_object_set_new(client_data, "ip", json_string(ip));
json_object_set_new(client_data, "cache_size", json_integer(cache_size));
json_object_set_new(client_data, "images", cache_arr);
json_array_append_new(clients, client_data);
dbi_result_free(result);
return 0;
}
static int og_cmd_cache_list(json_t *element, struct og_msg_params *params,
char *buffer_reply)
{
json_t *value, *root, *clients;
struct og_dbi *dbi;
const char *key;
int err = 0, i;
struct og_buffer og_buffer = {
.data = buffer_reply
};
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
else
err = -1;
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
clients = json_array();
if (!clients)
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
json_decref(clients);
return -1;
}
for (i = 0; i < params->ips_array_len; i++) {
if (og_dbi_client_cache_get(dbi, clients, params->ips_array[i]) < 0) {
json_decref(clients);
og_dbi_close(dbi);
return -1;
}
}
og_dbi_close(dbi);
root = json_object();
if (!root) {
json_decref(clients);
return -1;
}
json_object_set_new(root, "clients", clients);
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
static int og_cmd_cache_delete(json_t *element, struct og_msg_params *params,
char *buffer_reply)
{
json_t *value, *body, *image_arr = NULL;
const char *key;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "images")) {
if (json_typeof(value) != JSON_ARRAY) {
err = -1;
}
image_arr = value;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
if (!image_arr)
return -1;
body = json_copy(element);
json_object_del(body, "clients");
return og_send_request(OG_METHOD_POST, OG_CMD_CACHE_DELETE, params, body);
}
static int og_cmd_setup(json_t *element, struct og_msg_params *params)
{
json_t *value, *clients;
const char *key;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "type")) {
err = og_json_parse_string(value, &params->type);
params->flags |= OG_REST_PARAM_TYPE;
} else if (!strcmp(key, "disk")) {
err = og_json_parse_string(value, &params->disk);
params->flags |= OG_REST_PARAM_DISK;
} else if (!strcmp(key, "cache")) {
err = og_json_parse_string(value, &params->cache);
params->flags |= OG_REST_PARAM_CACHE;
} else if (!strcmp(key, "cache_size")) {
err = og_json_parse_string(value, &params->cache_size);
params->flags |= OG_REST_PARAM_CACHE_SIZE;
} else if (!strcmp(key, "partition_setup")) {
err = og_json_parse_partition_setup(value, params);
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_TYPE |
OG_REST_PARAM_DISK |
OG_REST_PARAM_CACHE |
OG_REST_PARAM_CACHE_SIZE |
OG_REST_PARAM_PART_0 |
OG_REST_PARAM_PART_1 |
OG_REST_PARAM_PART_2 |
OG_REST_PARAM_PART_3))
return -1;
clients = json_copy(element);
json_object_del(clients, "clients");
return og_send_request(OG_METHOD_POST, OG_CMD_SETUP, params, clients);
}
static int og_cmd_run_schedule(json_t *element, struct og_msg_params *params)
{
const char *key;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients"))
err = og_json_parse_clients(value, params);
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
NULL);
}
static LIST_HEAD(cmd_list);
const struct og_cmd *og_cmd_find(const char *client_ip)
{
struct og_cmd *cmd, *next;
list_for_each_entry_safe(cmd, next, &cmd_list, list) {
if (strcmp(cmd->ip, client_ip))
continue;
list_del(&cmd->list);
return cmd;
}
return NULL;
}
void og_cmd_free(const struct og_cmd *cmd)
{
struct og_msg_params *params = (struct og_msg_params *)&cmd->params;
int i;
for (i = 0; i < params->ips_array_len; i++) {
free((void *)params->netmask_array[i]);
free((void *)params->ips_array[i]);
free((void *)params->mac_array[i]);
}
free((void *)params->wol_type);
if (cmd->json)
json_decref(cmd->json);
free((void *)cmd->ip);
free((void *)cmd->mac);
free((void *)cmd);
}
static void og_cmd_init(struct og_cmd *cmd, enum og_rest_method method,
enum og_cmd_type type, json_t *root)
{
cmd->type = type;
cmd->method = method;
cmd->params.ips_array[0] = strdup(cmd->ip);
cmd->params.ips_array_len = 1;
cmd->json = root;
gettimeofday(&cmd->tv, NULL);
}
static int og_cmd_legacy_wol(const char *input, struct og_cmd *cmd)
{
char wol_type[2] = {};
const char *msglog;
struct og_dbi *dbi;
dbi_result result;
if (sscanf(input, "mar=%s", wol_type) != 1) {
syslog(LOG_ERR, "malformed database legacy input\n");
return -1;
}
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT aulas.netmask "
"FROM ordenadores "
"INNER JOIN aulas "
"ON ordenadores.idaula = aulas.idaula "
"WHERE ordenadores.ip = '%s'",
cmd->ip);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_next_row(result);
og_cmd_init(cmd, OG_METHOD_NO_HTTP, OG_CMD_WOL, NULL);
cmd->params.netmask_array[0] = dbi_result_get_string_copy(result,
"netmask");
cmd->params.mac_array[0] = strdup(cmd->mac);
cmd->params.wol_type = strdup(wol_type);
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
static int og_cmd_legacy_shell_run(const char *input, struct og_cmd *cmd)
{
json_t *root, *script, *echo;
script = json_string(input + 4);
echo = json_boolean(false);
root = json_object();
if (!root)
return -1;
json_object_set_new(root, "run", script);
json_object_set_new(root, "echo", echo);
og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SHELL_RUN, root);
return 0;
}
static int og_cmd_legacy_session(const char *input, struct og_cmd *cmd)
{
char part_str[OG_DB_SMALLINT_MAXLEN + 1];
char disk_str[OG_DB_SMALLINT_MAXLEN + 1];
json_t *root, *disk, *partition;
if (sscanf(input, "dsk=%s\rpar=%s\r", disk_str, part_str) != 2)
return -1;
partition = json_string(part_str);
disk = json_string(disk_str);
root = json_object();
if (!root)
return -1;
json_object_set_new(root, "partition", partition);
json_object_set_new(root, "disk", disk);
og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SESSION, root);
return 0;
}
static int og_cmd_legacy_poweroff(const char *input, struct og_cmd *cmd)
{
og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_POWEROFF, NULL);
return 0;
}
static int og_cmd_legacy_refresh(const char *input, struct og_cmd *cmd)
{
og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_REFRESH, NULL);
return 0;
}
static int og_cmd_legacy_reboot(const char *input, struct og_cmd *cmd)
{
og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_REBOOT, NULL);
return 0;
}
static int og_cmd_legacy_stop(const char *input, struct og_cmd *cmd)
{
og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_STOP, NULL);
return 0;
}
static int og_cmd_legacy_hardware(const char *input, struct og_cmd *cmd)
{
og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_HARDWARE, NULL);
return 0;
}
static int og_cmd_legacy_software(const char *input, struct og_cmd *cmd)
{
char part_str[OG_DB_SMALLINT_MAXLEN + 1];
char disk_str[OG_DB_SMALLINT_MAXLEN + 1];
json_t *root, *disk, *partition;
if (sscanf(input, "dsk=%s\rpar=%s\r", disk_str, part_str) != 2)
return -1;
partition = json_string(part_str);
disk = json_string(disk_str);
root = json_object();
if (!root)
return -1;
json_object_set_new(root, "partition", partition);
json_object_set_new(root, "disk", disk);
og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_SOFTWARE, root);
return 0;
}
static int og_cmd_legacy_image_create(const char *input, struct og_cmd *cmd)
{
json_t *root, *disk, *partition, *code, *image_id, *name, *repo;
struct og_image_legacy img = {};
if (sscanf(input, "dsk=%s\rpar=%s\rcpt=%s\ridi=%s\rnci=%s\ripr=%s\r",
img.disk, img.part, img.code, img.image_id, img.name,
img.repo) != 6)
return -1;
image_id = json_string(img.image_id);
partition = json_string(img.part);
code = json_string(img.code);
name = json_string(img.name);
repo = json_string(img.repo);
disk = json_string(img.disk);
root = json_object();
if (!root)
return -1;
json_object_set_new(root, "partition", partition);
json_object_set_new(root, "repository", repo);
json_object_set_new(root, "id", image_id);
json_object_set_new(root, "code", code);
json_object_set_new(root, "name", name);
json_object_set_new(root, "disk", disk);
og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_CREATE, root);
return 0;
}
#define OG_DB_RESTORE_TYPE_MAXLEN 64
static int og_cmd_legacy_image_restore(const char *input, struct og_cmd *cmd)
{
json_t *root, *disk, *partition, *image_id, *name, *repo;
char restore_type_str[OG_DB_RESTORE_TYPE_MAXLEN + 1] = {};
char software_id_str[OG_DB_INT_MAXLEN + 1] = {};
json_t *software_id, *restore_type;
struct og_image_legacy img = {};
if (sscanf(input,
"dsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
"ipr=%s\rifs=%s\rptc=%[^\r]\r",
img.disk, img.part, img.image_id, img.name, img.repo,
software_id_str, restore_type_str) != 7)
return -1;
restore_type = json_string(restore_type_str);
software_id = json_string(software_id_str);
image_id = json_string(img.image_id);
partition = json_string(img.part);
name = json_string(img.name);
repo = json_string(img.repo);
disk = json_string(img.disk);
root = json_object();
if (!root)
return -1;
json_object_set_new(root, "profile", software_id);
json_object_set_new(root, "partition", partition);
json_object_set_new(root, "type", restore_type);
json_object_set_new(root, "repository", repo);
json_object_set_new(root, "id", image_id);
json_object_set_new(root, "name", name);
json_object_set_new(root, "disk", disk);
og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, root);
return 0;
}
#define OG_PARTITION_TABLE_TYPE_MAXLEN 5
static int og_cmd_legacy_setup(const char *input, struct og_cmd *cmd)
{
json_t *root, *disk, *cache, *cache_size, *partition_setup, *object;
char part_table_type_str[OG_PARTITION_TABLE_TYPE_MAXLEN + 1];
struct og_legacy_partition part_cfg[OG_PARTITION_MAX] = {};
json_t *part_table_type, *part, *code, *fs, *size, *format;
char cache_size_str [OG_DB_INT_MAXLEN + 1];
char disk_str [OG_DB_SMALLINT_MAXLEN + 1];
unsigned int partition_len = 0;
const char *in_ptr;
char cache_str[2];
if (sscanf(input, "ttp=%s\rdsk=%s\rcfg=dis=%*[^*]*che=%[^*]*tch=%[^!]!",
part_table_type_str, disk_str, cache_str, cache_size_str) != 4)
return -1;
in_ptr = strstr(input, "!") + 1;
while (strlen(in_ptr) > 0) {
if(sscanf(in_ptr,
"par=%[^*]*cpt=%[^*]*sfi=%[^*]*tam=%[^*]*ope=%[^%%]%%",
part_cfg[partition_len].partition,
part_cfg[partition_len].code,
part_cfg[partition_len].filesystem,
part_cfg[partition_len].size,
part_cfg[partition_len].format) != 5)
return -1;
in_ptr = strstr(in_ptr, "%") + 1;
partition_len++;
}
root = json_object();
if (!root)
return -1;
part_table_type = json_string(part_table_type_str);
cache_size = json_string(cache_size_str);
cache = json_string(cache_str);
partition_setup = json_array();
disk = json_string(disk_str);
for (unsigned int i = 0; i < partition_len; ++i) {
object = json_object();
if (!object) {
json_decref(root);
return -1;
}
part = json_string(part_cfg[i].partition);
fs = json_string(part_cfg[i].filesystem);
format = json_string(part_cfg[i].format);
code = json_string(part_cfg[i].code);
size = json_string(part_cfg[i].size);
json_object_set_new(object, "partition", part);
json_object_set_new(object, "filesystem", fs);
json_object_set_new(object, "format", format);
json_object_set_new(object, "code", code);
json_object_set_new(object, "size", size);
json_array_append_new(partition_setup, object);
}
json_object_set_new(root, "partition_setup", partition_setup);
json_object_set_new(root, "cache_size", cache_size);
json_object_set_new(root, "type", part_table_type);
json_object_set_new(root, "cache", cache);
json_object_set_new(root, "disk", disk);
og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SETUP, root);
return 0;
}
static int og_cmd_legacy_run_schedule(const char *input, struct og_cmd *cmd)
{
og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, NULL);
return 0;
}
static int og_cmd_legacy(const char *input, struct og_cmd *cmd)
{
char legacy_cmd[32] = {};
int err = -1;
if (sscanf(input, "nfn=%31s\r", legacy_cmd) != 1) {
syslog(LOG_ERR, "malformed database legacy input\n");
return -1;
}
input = strchr(input, '\r') + 1;
if (!strcmp(legacy_cmd, "Arrancar")) {
err = og_cmd_legacy_wol(input, cmd);
} else if (!strcmp(legacy_cmd, "EjecutarScript")) {
err = og_cmd_legacy_shell_run(input, cmd);
} else if (!strcmp(legacy_cmd, "IniciarSesion")) {
err = og_cmd_legacy_session(input, cmd);
} else if (!strcmp(legacy_cmd, "Apagar")) {
err = og_cmd_legacy_poweroff(input, cmd);
} else if (!strcmp(legacy_cmd, "Actualizar")) {
err = og_cmd_legacy_refresh(input, cmd);
} else if (!strcmp(legacy_cmd, "Reiniciar")) {
err = og_cmd_legacy_reboot(input, cmd);
} else if (!strcmp(legacy_cmd, "Purgar")) {
err = og_cmd_legacy_stop(input, cmd);
} else if (!strcmp(legacy_cmd, "InventarioHardware")) {
err = og_cmd_legacy_hardware(input, cmd);
} else if (!strcmp(legacy_cmd, "InventarioSoftware")) {
err = og_cmd_legacy_software(input, cmd);
} else if (!strcmp(legacy_cmd, "CrearImagen")) {
err = og_cmd_legacy_image_create(input, cmd);
} else if (!strcmp(legacy_cmd, "RestaurarImagen")) {
err = og_cmd_legacy_image_restore(input, cmd);
} else if (!strcmp(legacy_cmd, "Configurar")) {
err = og_cmd_legacy_setup(input, cmd);
} else if (!strcmp(legacy_cmd, "EjecutaComandosPendientes") ||
!strcmp(legacy_cmd, "Actualizar")) {
err = og_cmd_legacy_run_schedule(input, cmd);
}
return err;
}
static int og_dbi_add_action(const struct og_dbi *dbi, struct og_task *task,
struct og_cmd *cmd)
{
char start_date_string[24];
struct tm *start_date;
const char *msglog;
dbi_result result;
time_t now;
time(&now);
start_date = localtime(&now);
sprintf(start_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
start_date->tm_year + 1900, start_date->tm_mon + 1,
start_date->tm_mday, start_date->tm_hour, start_date->tm_min,
start_date->tm_sec);
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO acciones (idordenador, "
"tipoaccion, idtipoaccion, descriaccion, ip, "
"sesion, idcomando, parametros, fechahorareg, "
"estado, resultado, ambito, idambito, "
"restrambito, idprocedimiento, idcentro, "
"idprogramacion) "
"VALUES (%d, %d, %d, '%s', '%s', %d, %d, '%s', "
"'%s', %d, %d, %d, %d, '%s', %d, %d, %d)",
cmd->client_id, EJECUCION_TAREA, task->task_id,
"", cmd->ip, task->session, task->command_id,
task->params, start_date_string,
ACCION_INICIADA, ACCION_SINRESULTADO,
task->type_scope, task->scope, "",
task->procedure_id, task->center_id,
task->schedule_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
cmd->id = dbi_conn_sequence_last(dbi->conn, NULL);
if (!task->session) {
task->session = cmd->id;
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"UPDATE acciones SET sesion=%d "
"WHERE idaccion=%d",
task->session, cmd->id);
}
dbi_result_free(result);
return 0;
}
static int og_queue_task_command(struct og_dbi *dbi, struct og_task *task,
char *query)
{
struct og_cmd *cmd;
const char *msglog;
dbi_result result;
result = dbi_conn_queryf(dbi->conn, query);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
cmd = (struct og_cmd *)calloc(1, sizeof(struct og_cmd));
if (!cmd) {
dbi_result_free(result);
return -1;
}
cmd->client_id = dbi_result_get_uint(result, "idordenador");
cmd->ip = strdup(dbi_result_get_string(result, "ip"));
cmd->mac = strdup(dbi_result_get_string(result, "mac"));
og_cmd_legacy(task->params, cmd);
if (task->procedure_id) {
if (og_dbi_add_action(dbi, task, cmd)) {
dbi_result_free(result);
return -1;
}
} else {
cmd->id = task->task_id;
}
list_add_tail(&cmd->list, &cmd_list);
}
dbi_result_free(result);
return 0;
}
static int og_queue_task_group_clients(struct og_dbi *dbi, struct og_task *task,
char *query)
{
const char *msglog;
dbi_result result;
result = dbi_conn_queryf(dbi->conn, query);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
sprintf(query, "SELECT idgrupo FROM gruposordenadores "
"WHERE grupoid=%d", group_id);
if (og_queue_task_group_clients(dbi, task, query)) {
dbi_result_free(result);
return -1;
}
sprintf(query,"SELECT ip, mac, idordenador FROM ordenadores "
"WHERE grupoid=%d", group_id);
if (og_queue_task_command(dbi, task, query)) {
dbi_result_free(result);
return -1;
}
}
dbi_result_free(result);
return 0;
}
static int og_queue_task_group_classrooms(struct og_dbi *dbi,
struct og_task *task, char *query)
{
const char *msglog;
dbi_result result;
result = dbi_conn_queryf(dbi->conn, query);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
sprintf(query, "SELECT idgrupo FROM grupos "
"WHERE grupoid=%d AND tipo=%d", group_id, AMBITO_GRUPOSAULAS);
if (og_queue_task_group_classrooms(dbi, task, query)) {
dbi_result_free(result);
return -1;
}
sprintf(query,
"SELECT ip,mac,idordenador "
"FROM ordenadores INNER JOIN aulas "
"WHERE ordenadores.idaula=aulas.idaula "
"AND aulas.grupoid=%d",
group_id);
if (og_queue_task_command(dbi, task, query)) {
dbi_result_free(result);
return -1;
}
}
dbi_result_free(result);
return 0;
}
static int og_queue_task_clients(struct og_dbi *dbi, struct og_task *task)
{
char query[4096];
switch (task->type_scope) {
case AMBITO_CENTROS:
sprintf(query,
"SELECT ip,mac,idordenador "
"FROM ordenadores INNER JOIN aulas "
"WHERE ordenadores.idaula=aulas.idaula "
"AND idcentro=%d",
task->scope);
return og_queue_task_command(dbi, task, query);
case AMBITO_GRUPOSAULAS:
sprintf(query,
"SELECT idgrupo FROM grupos "
"WHERE idgrupo=%i AND tipo=%d",
task->scope, AMBITO_GRUPOSAULAS);
return og_queue_task_group_classrooms(dbi, task, query);
case AMBITO_AULAS:
sprintf(query,
"SELECT ip,mac,idordenador FROM ordenadores "
"WHERE idaula=%d",
task->scope);
return og_queue_task_command(dbi, task, query);
case AMBITO_GRUPOSORDENADORES:
sprintf(query,
"SELECT idgrupo FROM gruposordenadores "
"WHERE idgrupo = %d",
task->scope);
return og_queue_task_group_clients(dbi, task, query);
case AMBITO_ORDENADORES:
sprintf(query,
"SELECT ip, mac, idordenador FROM ordenadores "
"WHERE idordenador = %d",
task->scope);
return og_queue_task_command(dbi, task, query);
}
return 0;
}
int og_dbi_queue_procedure(struct og_dbi *dbi, struct og_task *task)
{
uint32_t procedure_id;
const char *msglog;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"SELECT parametros, procedimientoid, idcomando "
"FROM procedimientos_acciones "
"WHERE idprocedimiento=%d ORDER BY orden", task->procedure_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
procedure_id = dbi_result_get_uint(result, "procedimientoid");
if (procedure_id > 0) {
task->procedure_id = procedure_id;
if (og_dbi_queue_procedure(dbi, task))
return -1;
continue;
}
task->params = dbi_result_get_string(result, "parametros");
task->command_id = dbi_result_get_uint(result, "idcomando");
if (og_queue_task_clients(dbi, task))
return -1;
}
dbi_result_free(result);
return 0;
}
static int og_dbi_queue_task(struct og_dbi *dbi, uint32_t task_id,
uint32_t schedule_id)
{
struct og_task task = {};
uint32_t task_id_next;
const char *msglog;
dbi_result result;
task.schedule_id = schedule_id;
result = dbi_conn_queryf(dbi->conn,
"SELECT tareas_acciones.orden, "
"tareas_acciones.idprocedimiento, "
"tareas_acciones.tareaid, "
"tareas.idtarea, "
"tareas.idcentro, "
"tareas.ambito, "
"tareas.idambito, "
"tareas.restrambito "
" FROM tareas"
" INNER JOIN tareas_acciones ON tareas_acciones.idtarea=tareas.idtarea"
" WHERE tareas_acciones.idtarea=%u ORDER BY tareas_acciones.orden ASC", task_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
task_id_next = dbi_result_get_uint(result, "tareaid");
if (task_id_next > 0) {
if (og_dbi_queue_task(dbi, task_id_next, schedule_id))
return -1;
continue;
}
task.task_id = dbi_result_get_uint(result, "idtarea");
task.center_id = dbi_result_get_uint(result, "idcentro");
task.procedure_id = dbi_result_get_uint(result, "idprocedimiento");
task.type_scope = dbi_result_get_uint(result, "ambito");
task.scope = dbi_result_get_uint(result, "idambito");
task.filtered_scope = dbi_result_get_string(result, "restrambito");
og_dbi_queue_procedure(dbi, &task);
}
dbi_result_free(result);
return 0;
}
static int og_dbi_queue_command(struct og_dbi *dbi, uint32_t task_id,
uint32_t schedule_id)
{
struct og_task task = {};
const char *msglog;
dbi_result result;
char query[4096];
result = dbi_conn_queryf(dbi->conn,
"SELECT idaccion, idcentro, idordenador, parametros "
"FROM acciones "
"WHERE sesion = %u", task_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
task.task_id = dbi_result_get_uint(result, "idaccion");
task.center_id = dbi_result_get_uint(result, "idcentro");
task.scope = dbi_result_get_uint(result, "idordenador");
task.params = dbi_result_get_string(result, "parametros");
sprintf(query,
"SELECT ip, mac, idordenador FROM ordenadores "
"WHERE idordenador = %d",
task.scope);
if (og_queue_task_command(dbi, &task, query)) {
dbi_result_free(result);
return -1;
}
}
dbi_result_free(result);
return 0;
}
int og_dbi_update_action(uint32_t id, bool success)
{
char end_date_string[24];
struct tm *end_date;
const char *msglog;
struct og_dbi *dbi;
uint8_t status = 2;
dbi_result result;
time_t now;
if (!id)
return 0;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
time(&now);
end_date = localtime(&now);
sprintf(end_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
end_date->tm_year + 1900, end_date->tm_mon + 1,
end_date->tm_mday, end_date->tm_hour, end_date->tm_min,
end_date->tm_sec);
result = dbi_conn_queryf(dbi->conn,
"UPDATE acciones SET fechahorafin='%s', "
"estado=%d, resultado=%d WHERE idaccion=%d",
end_date_string, ACCION_FINALIZADA,
status - success, id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
void og_schedule_run(unsigned int task_id, unsigned int schedule_id,
enum og_schedule_type type)
{
struct og_msg_params params = {};
struct in_addr addr, netmask;
struct og_cmd *cmd, *next;
bool duplicated = false;
struct og_dbi *dbi;
unsigned int i;
int sd;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return;
}
switch (type) {
case OG_SCHEDULE_TASK:
og_dbi_queue_task(dbi, task_id, schedule_id);
break;
case OG_SCHEDULE_PROCEDURE:
case OG_SCHEDULE_COMMAND:
og_dbi_queue_command(dbi, task_id, schedule_id);
break;
}
og_dbi_close(dbi);
list_for_each_entry(cmd, &cmd_list, list) {
for (i = 0; i < params.ips_array_len; i++) {
if (!strncmp(cmd->ip, params.ips_array[i],
OG_DB_IP_MAXLEN)) {
duplicated = true;
break;
}
}
if (!duplicated)
params.ips_array[params.ips_array_len++] = strdup(cmd->ip);
else
duplicated = false;
}
sd = wol_socket_open();
if (sd < 0) {
syslog(LOG_ERR, "cannot open wol socket (%s:%d)\n",
__func__, __LINE__);
goto err_out;
}
list_for_each_entry_safe(cmd, next, &cmd_list, list) {
if (cmd->type != OG_CMD_WOL)
continue;
for (i = 0; i < cmd->params.ips_array_len; i++) {
if (inet_aton(cmd->params.ips_array[i], &addr) < 0)
continue;
if (inet_aton(cmd->params.netmask_array[i], &netmask) < 0)
continue;
if (wake_up(sd, &addr, &netmask,
cmd->params.mac_array[i],
atoi(cmd->params.wol_type)) < 0) {
syslog(LOG_ERR, "Failed to send wol packet to %s\n",
params.ips_array[i]);
continue;
}
og_dbi_update_action(cmd->id, true);
}
list_del(&cmd->list);
og_cmd_free(cmd);
}
close(sd);
og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, &params, NULL);
err_out:
for (i = 0; i < params.ips_array_len; i++)
free((void *)params.ips_array[i]);
}
static int og_cmd_task_post(json_t *element, struct og_msg_params *params)
{
struct og_cmd *cmd;
struct og_dbi *dbi;
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "task")) {
err = og_json_parse_string(value, &params->task_id);
params->flags |= OG_REST_PARAM_TASK;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_TASK))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
og_schedule_run(atoi(params->task_id), 0, OG_SCHEDULE_TASK);
og_dbi_close(dbi);
list_for_each_entry(cmd, &cmd_list, list)
params->ips_array[params->ips_array_len++] = cmd->ip;
return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
NULL);
}
#define OG_QUERY_MAXLEN 4096
static int og_dbi_scope_get_computer(const struct og_dbi *dbi, json_t *array,
const char* query)
{
const char *computer_name, *computer_ip;
uint32_t computer_id;
const char *msglog;
dbi_result result;
json_t *computer;
result = dbi_conn_queryf(dbi->conn, query);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
computer_id = dbi_result_get_uint(result, "idordenador");
computer_name = dbi_result_get_string(result, "nombreordenador");
computer_ip = dbi_result_get_string(result, "ip");
computer = json_object();
if (!computer) {
dbi_result_free(result);
return -1;
}
json_object_set_new(computer, "name", json_string(computer_name));
json_object_set_new(computer, "type", json_string("computer"));
json_object_set_new(computer, "id", json_integer(computer_id));
json_object_set_new(computer, "scope", json_array());
json_object_set_new(computer, "ip", json_string(computer_ip));
json_array_append(array, computer);
json_decref(computer);
}
dbi_result_free(result);
return 0;
}
static int og_dbi_scope_get_computer_from_room(const struct og_dbi *dbi,
json_t *array, char *query,
const uint32_t room_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idordenador, nombreordenador, ip "
"FROM ordenadores WHERE idaula=%d and grupoid=0",
room_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_computer(dbi, array, query);
}
static int og_dbi_scope_get_computer_from_computers(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t computers_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idordenador, nombreordenador, ip "
"FROM ordenadores WHERE grupoid=%d",
computers_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_computer(dbi, array, query);
}
static int og_dbi_scope_get_computers_from_computers(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t group_id);
static int og_dbi_scope_get_computers(const struct og_dbi *dbi, json_t *array,
char *query, bool in_room)
{
const char *msglog, *computers_name;
json_t *computers, *scope_array;
uint32_t computers_id;
uint32_t marker = 0;
dbi_result result;
if (in_room)
marker = OG_COMPUTER_FOLDER_MARKER;
result = dbi_conn_queryf(dbi->conn, query);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
computers_id = dbi_result_get_uint(result, "idgrupo");
computers_name = dbi_result_get_string(result,
"nombregrupoordenador");
computers = json_object();
if (!computers) {
dbi_result_free(result);
return -1;
}
json_object_set_new(computers, "name",
json_string(computers_name));
json_object_set_new(computers, "type", json_string("folder"));
json_object_set_new(computers, "id",
json_integer(computers_id | marker));
json_object_set_new(computers, "scope", json_array());
json_array_append(array, computers);
json_decref(computers);
scope_array = json_object_get(computers, "scope");
if (!scope_array) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_computers_from_computers(dbi,
scope_array,
query,
computers_id)) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_computer_from_computers(dbi,
scope_array,
query,
computers_id)) {
dbi_result_free(result);
return -1;
}
}
dbi_result_free(result);
return 0;
}
static int og_dbi_scope_get_computers_from_room(const struct og_dbi *dbi,
json_t *array, char *query,
const uint32_t room_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idgrupo, nombregrupoordenador "
"FROM gruposordenadores "
"WHERE idaula=%d AND grupoid=0",
room_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_computers(dbi, array, query, true);
}
static int og_dbi_scope_get_computers_from_computers(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t group_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idgrupo, nombregrupoordenador "
"FROM gruposordenadores WHERE grupoid=%d",
group_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_computers(dbi, array, query, false);
}
static int og_dbi_scope_get_room(const struct og_dbi *dbi, json_t *array,
char *query)
{
const char *msglog, *room_name;
json_t *room, *scope_array;
dbi_result result;
uint32_t room_id;
result = dbi_conn_queryf(dbi->conn, query);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
room_id = dbi_result_get_uint(result, "idaula");
room_name = dbi_result_get_string(result, "nombreaula");
room = json_object();
if (!room) {
dbi_result_free(result);
return -1;
}
json_object_set_new(room, "name", json_string(room_name));
json_object_set_new(room, "type", json_string("room"));
json_object_set_new(room, "id", json_integer(room_id));
json_object_set_new(room, "scope", json_array());
json_array_append(array, room);
json_decref(room);
scope_array = json_object_get(room, "scope");
if (!scope_array) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_computers_from_room(dbi, scope_array,
query, room_id)) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_computer_from_room(dbi, scope_array,
query, room_id)) {
dbi_result_free(result);
return -1;
}
}
dbi_result_free(result);
return 0;
}
static int og_dbi_scope_get_room_from_group(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t group_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idaula, nombreaula "
"FROM aulas WHERE grupoid=%d", group_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_room(dbi, array, query);
}
static int og_dbi_scope_get_room_from_center(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t center_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idaula, nombreaula "
"FROM aulas WHERE idcentro=%d AND grupoid=0",
center_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_room(dbi, array, query);
}
static int og_dbi_scope_get_group_from_group(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t group_id);
static int og_dbi_scope_get_group(const struct og_dbi *dbi,
json_t *array,
char *query)
{
const char *msglog, *group_name;
json_t *group, *scope_array;
dbi_result result;
uint32_t group_id;
result = dbi_conn_queryf(dbi->conn, query);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
group_id = dbi_result_get_uint(result, "idgrupo");
group_name = dbi_result_get_string(result, "nombregrupo");
group = json_object();
if (!group) {
dbi_result_free(result);
return -1;
}
json_object_set_new(group, "name", json_string(group_name));
json_object_set_new(group, "type", json_string("folder"));
json_object_set_new(group, "id", json_integer(group_id));
json_object_set_new(group, "scope", json_array());
json_array_append(array, group);
json_decref(group);
scope_array = json_object_get(group, "scope");
if (!scope_array) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_group_from_group(dbi, scope_array, query,
group_id)) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_room_from_group(dbi, scope_array, query,
group_id)) {
dbi_result_free(result);
return -1;
}
}
dbi_result_free(result);
return 0;
}
static int og_dbi_scope_get_group_from_group(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t group_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idgrupo, nombregrupo "
"FROM grupos WHERE grupoid=%d", group_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_group(dbi, array, query);
}
static int og_dbi_scope_get_group_from_center(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t center_id)
{
int group_type_room = 2;
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idgrupo, nombregrupo "
"FROM grupos "
"WHERE idcentro=%d AND grupoid=0 AND tipo=%d",
center_id, group_type_room);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_group(dbi, array, query);
}
static int og_dbi_scope_get(struct og_dbi *dbi, json_t *array)
{
const char *msglog, *center_name;
json_t *center, *scope_array;
char query[OG_QUERY_MAXLEN];
uint32_t center_id;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"SELECT nombrecentro, idcentro FROM centros");
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
center_id = dbi_result_get_uint(result, "idcentro");
center_name = dbi_result_get_string(result, "nombrecentro");
center = json_object();
if (!center) {
dbi_result_free(result);
return -1;
}
scope_array = json_array();
if (!scope_array) {
dbi_result_free(result);
json_decref(center);
return -1;
}
json_object_set_new(center, "name", json_string(center_name));
json_object_set_new(center, "type", json_string("center"));
json_object_set_new(center, "id", json_integer(center_id));
json_object_set_new(center, "scope", scope_array);
json_array_append(array, center);
json_decref(center);
if (og_dbi_scope_get_group_from_center(dbi, scope_array, query,
center_id)) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_room_from_center(dbi, scope_array, query,
center_id)) {
dbi_result_free(result);
return -1;
}
}
dbi_result_free(result);
return 0;
}
static int og_cmd_scope_get(json_t *element, struct og_msg_params *params,
char *buffer_reply)
{
struct og_buffer og_buffer = {
.data = buffer_reply
};
json_t *root, *array;
struct og_dbi *dbi;
root = json_object();
if (!root)
return -1;
array = json_array();
if (!array) {
json_decref(root);
return -1;
}
json_object_set_new(root, "scope", array);
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
json_decref(root);
return -1;
}
if (og_dbi_scope_get(dbi, array)) {
og_dbi_close(dbi);
json_decref(root);
return -1;
}
og_dbi_close(dbi);
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
int og_dbi_schedule_get(void)
{
uint32_t schedule_id, task_id;
struct og_schedule_time time;
struct og_dbi *dbi;
const char *msglog;
dbi_result result;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT idprogramacion, tipoaccion, identificador, "
"sesion, annos, meses, diario, dias, semanas, horas, "
"ampm, minutos FROM programaciones "
"WHERE suspendida = 0");
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
while (dbi_result_next_row(result)) {
memset(&time, 0, sizeof(time));
schedule_id = dbi_result_get_uint(result, "idprogramacion");
task_id = dbi_result_get_uint(result, "identificador");
time.years = dbi_result_get_uint(result, "annos");
time.months = dbi_result_get_uint(result, "meses");
time.weeks = dbi_result_get_uint(result, "semanas");
time.week_days = dbi_result_get_uint(result, "dias");
time.days = dbi_result_get_uint(result, "diario");
time.hours = dbi_result_get_uint(result, "horas");
time.am_pm = dbi_result_get_uint(result, "ampm");
time.minutes = dbi_result_get_uint(result, "minutos");
time.check_stale = true;
og_schedule_create(schedule_id, task_id, OG_SCHEDULE_TASK,
&time);
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
static int og_dbi_schedule_create(struct og_dbi *dbi,
struct og_msg_params *params,
uint32_t *schedule_id,
enum og_schedule_type schedule_type)
{
uint8_t suspended = 0;
uint32_t session = 0;
const char *msglog;
dbi_result result;
uint8_t type;
switch (schedule_type) {
case OG_SCHEDULE_TASK:
type = 3;
break;
case OG_SCHEDULE_PROCEDURE:
type = 2;
break;
case OG_SCHEDULE_COMMAND:
session = atoi(params->task_id);
type = 1;
break;
}
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO programaciones (tipoaccion,"
" identificador, nombrebloque, annos, meses,"
" semanas, dias, diario, horas, ampm, minutos,"
" suspendida, sesion) VALUES (%d, %s, '%s',"
" %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)",
type, params->task_id, params->name,
params->time.years, params->time.months,
params->time.weeks, params->time.week_days,
params->time.days, params->time.hours,
params->time.am_pm, params->time.minutes,
suspended, session);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
*schedule_id = dbi_conn_sequence_last(dbi->conn, NULL);
return 0;
}
static int og_dbi_schedule_update(struct og_dbi *dbi,
struct og_msg_params *params)
{
const char *msglog;
dbi_result result;
uint8_t type = 3;
result = dbi_conn_queryf(dbi->conn,
"UPDATE programaciones SET tipoaccion=%d, "
"identificador='%s', nombrebloque='%s', "
"annos=%d, meses=%d, "
"diario=%d, horas=%d, ampm=%d, minutos=%d "
"WHERE idprogramacion='%s'",
type, params->task_id, params->name,
params->time.years, params->time.months,
params->time.days, params->time.hours,
params->time.am_pm, params->time.minutes,
params->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
static int og_dbi_schedule_delete(struct og_dbi *dbi, uint32_t id)
{
const char *msglog;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM programaciones WHERE idprogramacion=%d",
id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
struct og_db_schedule {
uint32_t id;
uint32_t task_id;
const char *name;
struct og_schedule_time time;
uint32_t week_days;
uint32_t weeks;
uint32_t suspended;
uint32_t session;
};
static int og_dbi_schedule_get_json(struct og_dbi *dbi, json_t *root,
const char *task_id, const char *schedule_id)
{
struct og_db_schedule schedule;
json_t *obj, *array;
const char *msglog;
dbi_result result;
int err = 0;
if (task_id) {
result = dbi_conn_queryf(dbi->conn,
"SELECT idprogramacion,"
" identificador, nombrebloque,"
" annos, meses, diario, dias,"
" semanas, horas, ampm,"
" minutos,suspendida, sesion "
"FROM programaciones "
"WHERE identificador=%d",
atoi(task_id));
} else if (schedule_id) {
result = dbi_conn_queryf(dbi->conn,
"SELECT idprogramacion,"
" identificador, nombrebloque,"
" annos, meses, diario, dias,"
" semanas, horas, ampm,"
" minutos,suspendida, sesion "
"FROM programaciones "
"WHERE idprogramacion=%d",
atoi(schedule_id));
} else {
result = dbi_conn_queryf(dbi->conn,
"SELECT idprogramacion,"
" identificador, nombrebloque,"
" annos, meses, diario, dias,"
" semanas, horas, ampm,"
" minutos,suspendida, sesion "
"FROM programaciones");
}
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
array = json_array();
if (!array)
return -1;
while (dbi_result_next_row(result)) {
schedule.id = dbi_result_get_uint(result, "idprogramacion");
schedule.task_id = dbi_result_get_uint(result, "identificador");
schedule.name = dbi_result_get_string(result, "nombrebloque");
schedule.time.years = dbi_result_get_uint(result, "annos");
schedule.time.months = dbi_result_get_uint(result, "meses");
schedule.time.days = dbi_result_get_uint(result, "diario");
schedule.time.hours = dbi_result_get_uint(result, "horas");
schedule.time.am_pm = dbi_result_get_uint(result, "ampm");
schedule.time.minutes = dbi_result_get_uint(result, "minutos");
schedule.week_days = dbi_result_get_uint(result, "dias");
schedule.weeks = dbi_result_get_uint(result, "semanas");
schedule.suspended = dbi_result_get_uint(result, "suspendida");
schedule.session = dbi_result_get_uint(result, "sesion");
obj = json_object();
if (!obj) {
err = -1;
break;
}
json_object_set_new(obj, "id", json_integer(schedule.id));
json_object_set_new(obj, "task", json_integer(schedule.task_id));
json_object_set_new(obj, "name", json_string(schedule.name));
json_object_set_new(obj, "years", json_integer(schedule.time.years));
json_object_set_new(obj, "months", json_integer(schedule.time.months));
json_object_set_new(obj, "days", json_integer(schedule.time.days));
json_object_set_new(obj, "hours", json_integer(schedule.time.hours));
json_object_set_new(obj, "am_pm", json_integer(schedule.time.am_pm));
json_object_set_new(obj, "minutes", json_integer(schedule.time.minutes));
json_object_set_new(obj, "week_days", json_integer(schedule.week_days));
json_object_set_new(obj, "weeks", json_integer(schedule.weeks));
json_object_set_new(obj, "suspended", json_integer(schedule.suspended));
json_object_set_new(obj, "session", json_integer(schedule.session));
json_array_append_new(array, obj);
}
json_object_set_new(root, "schedule", array);
dbi_result_free(result);
return err;
}
static int og_task_schedule_create(struct og_msg_params *params)
{
enum og_schedule_type type;
uint32_t schedule_id;
struct og_dbi *dbi;
int err;
if (!strcmp(params->type, "task"))
type = OG_SCHEDULE_TASK;
else if (!strcmp(params->type, "procedure"))
type = OG_SCHEDULE_PROCEDURE;
else if (!strcmp(params->type, "command"))
type = OG_SCHEDULE_COMMAND;
else
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
err = og_dbi_schedule_create(dbi, params, &schedule_id, type);
if (err < 0) {
og_dbi_close(dbi);
return -1;
}
og_schedule_create(schedule_id, atoi(params->task_id), type,
&params->time);
og_schedule_refresh(og_loop);
og_dbi_close(dbi);
return 0;
}
static uint32_t og_tm_years_mask(struct tm *tm)
{
int i, j = 0;
for (i = 2010; i < 2026; i++, j++) {
if (tm->tm_year + 1900 == i)
break;
}
return (1 << j);
}
static uint32_t og_tm_months_mask(struct tm *tm)
{
return 1 << tm->tm_mon;
}
static uint16_t og_tm_hours_mask(struct tm *tm)
{
return tm->tm_hour >= 12 ? 1 << (tm->tm_hour - 12) : 1 << tm->tm_hour;
}
static uint32_t og_tm_ampm(struct tm *tm)
{
return tm->tm_hour < 12 ? 0 : 1;
}
static uint32_t og_tm_days_mask(struct tm *tm)
{
return 1 << (tm->tm_mday - 1);
}
static void og_schedule_time_now(struct og_schedule_time *ogtime)
{
struct tm *tm;
time_t now;
now = time(NULL);
tm = localtime(&now);
ogtime->years = og_tm_years_mask(tm);
ogtime->months = og_tm_months_mask(tm);
ogtime->weeks = 0;
ogtime->week_days = 0;
ogtime->days = og_tm_days_mask(tm);
ogtime->hours = og_tm_hours_mask(tm);
ogtime->am_pm = og_tm_ampm(tm);
ogtime->minutes = tm->tm_min;
}
static int og_cmd_schedule_create(json_t *element, struct og_msg_params *params)
{
bool when = false;
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "task")) {
err = og_json_parse_string(value, &params->task_id);
params->flags |= OG_REST_PARAM_TASK;
} else if (!strcmp(key, "name")) {
err = og_json_parse_string(value, &params->name);
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "when")) {
err = og_json_parse_time_params(value, params);
when = true;
} else if (!strcmp(key, "type")) {
err = og_json_parse_string(value, &params->type);
params->flags |= OG_REST_PARAM_TYPE;
}
if (err < 0)
return err;
}
if (!when) {
params->time.check_stale = false;
og_schedule_time_now(&params->time);
params->flags |= OG_REST_PARAM_TIME_YEARS |
OG_REST_PARAM_TIME_MONTHS |
OG_REST_PARAM_TIME_WEEKS |
OG_REST_PARAM_TIME_WEEK_DAYS |
OG_REST_PARAM_TIME_DAYS |
OG_REST_PARAM_TIME_HOURS |
OG_REST_PARAM_TIME_AM_PM |
OG_REST_PARAM_TIME_MINUTES;
} else {
params->time.check_stale = true;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_TASK |
OG_REST_PARAM_NAME |
OG_REST_PARAM_TIME_YEARS |
OG_REST_PARAM_TIME_MONTHS |
OG_REST_PARAM_TIME_WEEKS |
OG_REST_PARAM_TIME_WEEK_DAYS |
OG_REST_PARAM_TIME_DAYS |
OG_REST_PARAM_TIME_HOURS |
OG_REST_PARAM_TIME_MINUTES |
OG_REST_PARAM_TIME_AM_PM |
OG_REST_PARAM_TYPE))
return -1;
return og_task_schedule_create(params);
}
static int og_cmd_schedule_update(json_t *element, struct og_msg_params *params)
{
struct og_dbi *dbi;
bool when = false;
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "id")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
} else if (!strcmp(key, "task")) {
err = og_json_parse_string(value, &params->task_id);
params->flags |= OG_REST_PARAM_TASK;
} else if (!strcmp(key, "name")) {
err = og_json_parse_string(value, &params->name);
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "when")) {
err = og_json_parse_time_params(value, params);
when = true;
}
if (err < 0)
return err;
}
if (!when) {
params->time.check_stale = false;
og_schedule_time_now(&params->time);
params->flags |= OG_REST_PARAM_TIME_YEARS |
OG_REST_PARAM_TIME_MONTHS |
OG_REST_PARAM_TIME_WEEKS |
OG_REST_PARAM_TIME_WEEK_DAYS |
OG_REST_PARAM_TIME_DAYS |
OG_REST_PARAM_TIME_HOURS |
OG_REST_PARAM_TIME_AM_PM |
OG_REST_PARAM_TIME_MINUTES;
} else {
params->time.check_stale = true;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
OG_REST_PARAM_TASK |
OG_REST_PARAM_NAME |
OG_REST_PARAM_TIME_YEARS |
OG_REST_PARAM_TIME_MONTHS |
OG_REST_PARAM_TIME_DAYS |
OG_REST_PARAM_TIME_HOURS |
OG_REST_PARAM_TIME_MINUTES |
OG_REST_PARAM_TIME_AM_PM))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
err = og_dbi_schedule_update(dbi, params);
og_dbi_close(dbi);
if (err < 0)
return err;
og_schedule_update(og_loop, atoi(params->id), atoi(params->task_id),
&params->time);
og_schedule_refresh(og_loop);
return err;
}
static int og_cmd_schedule_delete(json_t *element, struct og_msg_params *params)
{
struct og_dbi *dbi;
const char *key;
json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "id")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
err = og_dbi_schedule_delete(dbi, atoi(params->id));
og_dbi_close(dbi);
og_schedule_delete(og_loop, atoi(params->id));
return err;
}
static int og_cmd_schedule_get(json_t *element, struct og_msg_params *params,
char *buffer_reply)
{
struct og_buffer og_buffer = {
.data = buffer_reply,
};
json_t *schedule_root;
struct og_dbi *dbi;
const char *key;
json_t *value;
int err = 0;
if (element) {
if (json_typeof(element) != JSON_OBJECT)
return -1;
json_object_foreach(element, key, value) {
if (!strcmp(key, "task")) {
err = og_json_parse_string(value,
&params->task_id);
} else if (!strcmp(key, "id")) {
err = og_json_parse_string(value, &params->id);
}
if (err < 0)
return err;
}
}
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
schedule_root = json_object();
if (!schedule_root) {
og_dbi_close(dbi);
return -1;
}
err = og_dbi_schedule_get_json(dbi, schedule_root,
params->task_id, params->id);
og_dbi_close(dbi);
if (err >= 0)
err = json_dump_callback(schedule_root, og_json_dump_clients,
&og_buffer, JSON_ENSURE_ASCII);
json_decref(schedule_root);
return err;
}
#define OG_LIVE_JSON_FILE_PATH "/opt/opengnsys/etc/ogliveinfo.json"
static int og_cmd_oglive_list(char *buffer_reply)
{
struct og_buffer og_buffer = {
.data = buffer_reply
};
json_error_t json_err;
json_t *root;
root = json_load_file(OG_LIVE_JSON_FILE_PATH, 0, &json_err);
if (!root) {
syslog(LOG_ERR, "malformed json line %d: %s\n",
json_err.line, json_err.text);
return -1;
}
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
static int og_cmd_post_center_add(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "name")) {
err = og_json_parse_string(value, &params->name);
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "comment")) {
err = og_json_parse_string(value, &params->comment);
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_NAME))
return -1;
if (!params->comment)
params->comment = "";
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT nombrecentro FROM centros WHERE nombrecentro='%s'",
params->name);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "Center with name %s already exists\n",
params->name);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO centros("
" nombrecentro,"
" comentarios,"
" identidad) VALUES ("
"'%s', '%s', 1)",
params->name, params->comment);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to add center to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
static int og_cmd_post_center_delete(json_t *element,
struct og_msg_params *params)
{
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
uint32_t image_id;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "id")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM centros WHERE idcentro=%s",
params->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows_affected(result) < 1) {
syslog(LOG_ERR, "delete did not modify any row (%s:%d)\n",
__func__, __LINE__);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"SELECT idimagen FROM imagenes WHERE idcentro=%s",
params->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
while (dbi_result_next_row(result)) {
image_id = dbi_result_get_uint(result, "idimagen");
err = og_delete_image(dbi, image_id);
if (err < 0) {
dbi_result_free(result);
og_dbi_close(dbi);
return err;
}
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
int og_procedure_add_steps(struct og_dbi *dbi, struct og_procedure *proc)
{
struct og_procedure_step *step;
const char *legacy_params;
const char *msglog;
dbi_result result;
int i;
for (i = 0; i < proc->num_steps; i++) {
step = &proc->steps[i];
switch (step->type) {
case OG_STEP_COMMAND:
legacy_params = og_msg_params_to_legacy(&step->cmd);
if (!legacy_params) {
og_dbi_close(dbi);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO procedimientos_acciones "
"(idprocedimiento, orden, parametros) "
"VALUES (%d, %d, '%s')",
proc->id,
step->position,
legacy_params);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR,
"failed to add procedure command to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
free((char *)legacy_params);
return -1;
}
dbi_result_free(result);
free((char *)legacy_params);
break;
case OG_STEP_PROCEDURE:
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO procedimientos_acciones "
"(idprocedimiento, orden, procedimientoid) "
"VALUES (%d, %d, %d)",
proc->id,
step->position,
step->procedure.id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR,
"failed to add procedure child to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
break;
case OG_STEP_TASK:
syslog(LOG_ERR, "Procedures can not include tasks. "
"Invalid step: %d\n",
step->position);
return -1;
break;
}
}
return 0;
}
static int og_cmd_post_procedure_add(json_t *element,
struct og_msg_params *params)
{
struct og_procedure proc = {};
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "center")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
} else if (!strcmp(key, "name")) {
err = og_json_parse_string(value, &params->name);
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "description")) {
err = og_json_parse_string(value, &params->comment);
} else if (!strcmp(key, "steps")) {
err = og_json_parse_procedure(value, &proc);
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
OG_REST_PARAM_NAME))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT descripcion FROM procedimientos "
"WHERE descripcion='%s' AND idcentro=%s",
params->name, params->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "Procedure with name %s already exists in the "
"center with id %s\n",
params->name, params->id);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO procedimientos("
"idcentro, descripcion, comentarios) "
"VALUES (%s, '%s', '%s')",
params->id, params->name, params->comment);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR,
"failed to add procedure to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
proc.id = dbi_conn_sequence_last(dbi->conn, NULL);
err = og_procedure_add_steps(dbi, &proc);
og_dbi_close(dbi);
return err;
}
static int og_cmd_post_procedure_delete(json_t *element,
struct og_msg_params *params)
{
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "id")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM procedimientos WHERE idprocedimiento=%s",
params->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
} else if (dbi_result_get_numrows_affected(result) < 1) {
syslog(LOG_ERR, "delete did not modify any row (%s:%d)\n",
__func__, __LINE__);
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
static int og_cmd_post_procedure_update(json_t *element,
struct og_msg_params *params)
{
struct og_procedure proc = {};
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "procedure")) {
err = og_json_parse_string(value, &params->task_id);
params->flags |= OG_REST_PARAM_TASK;
} else if (!strcmp(key, "center")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
} else if (!strcmp(key, "name")) {
err = og_json_parse_string(value, &params->name);
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "description")) {
err = og_json_parse_string(value, &params->comment);
} else if (!strcmp(key, "steps")) {
err = og_json_parse_procedure(value, &proc);
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_TASK |
OG_REST_PARAM_ID |
OG_REST_PARAM_NAME))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT descripcion FROM procedimientos "
"WHERE descripcion = '%s' AND idcentro = %s "
"AND idprocedimiento <> %s",
params->name, params->id, params->task_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "Procedure with name %s already exists in the "
"center with id %s\n",
params->name, params->id);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"UPDATE procedimientos SET idcentro = %s, "
"descripcion = '%s', comentarios = '%s' "
"WHERE idprocedimiento = %s",
params->id, params->name, params->comment,
params->task_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR,
"failed to update procedure %s (%s:%d) %s\n",
params->task_id, __func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM procedimientos_acciones "
"WHERE idprocedimiento = %s",
params->task_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR,
"failed to delete old procedure %s steps (%s:%d) %s\n",
params->task_id, __func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
proc.id = atoll(params->task_id);
err = og_procedure_add_steps(dbi, &proc);
og_dbi_close(dbi);
return err;
}
static int og_task_add_steps(struct og_dbi *dbi, struct og_procedure *task)
{
struct og_procedure_step *step;
const char *msglog;
dbi_result result;
int i;
for (i = 0; i < task->num_steps; i++) {
step = &task->steps[i];
switch (step->type) {
case OG_STEP_COMMAND:
syslog(LOG_ERR, "Tasks can not include commands. "
"Invalid step: %d\n",
step->position);
return -1;
break;
case OG_STEP_PROCEDURE:
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO tareas_acciones "
"(idtarea, orden, idprocedimiento) "
"VALUES (%d, %d, %d)",
task->id,
step->position,
step->procedure.id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR,
"failed to add procedure child to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
break;
case OG_STEP_TASK:
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO tareas_acciones "
"(idtarea, orden, tareaid) "
"VALUES (%d, %d, %d)",
task->id,
step->position,
step->procedure.id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR,
"failed to add task child to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
break;
}
}
return 0;
}
static int og_cmd_post_task_add(json_t *element,
struct og_msg_params *params)
{
struct og_procedure task = {};
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "center")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
} else if (!strcmp(key, "name")) {
err = og_json_parse_string(value, &params->name);
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "description")) {
err = og_json_parse_string(value, &params->comment);
} else if (!strcmp(key, "steps")) {
err = og_json_parse_procedure(value, &task);
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
OG_REST_PARAM_NAME))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT descripcion FROM tareas "
"WHERE descripcion='%s' AND idcentro=%s",
params->name, params->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "Task with name %s already exists in the "
"center with id %s\n",
params->name, params->id);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO tareas("
"idcentro, descripcion, comentarios) "
"VALUES (%s, '%s', '%s')",
params->id, params->name, params->comment);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR,
"failed to add task to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
task.id = dbi_conn_sequence_last(dbi->conn, NULL);
err = og_task_add_steps(dbi, &task);
og_dbi_close(dbi);
return err;
}
static int og_cmd_post_repository_update(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
struct og_repository repo = {};
const char *key, *msglog;
unsigned int repo_id;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "repo_id")) {
err = og_json_parse_uint(value, &repo_id);
params->flags |= OG_REST_PARAM_ID;
}
if (!strcmp(key, "name")) {
err = og_json_parse_string_copy(value,
repo.name,
sizeof(repo.name));
} else if (!strcmp(key, "ip")) {
err = og_json_parse_string_copy(value,
repo.ip,
sizeof(repo.ip));
} else if (!strcmp(key, "center")) {
err = og_json_parse_uint(value, &repo.center);
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"UPDATE repositorios"
" SET nombrerepositorio='%s',"
" ip='%s',"
" idcentro=%u"
" WHERE idrepositorio=%u;",
repo.name, repo.ip, repo.center, repo_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to update repository in database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (!dbi_result_get_numrows_affected(result)) {
syslog(LOG_ERR, "repository with id %u does not exist (%s:%d)\n",
repo_id, __func__, __LINE__);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
og_dbi_close(dbi);
return err;
}
static int og_cmd_post_repository_add(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
struct og_repository repo = {
.center = 1, /* never used, set it to 1. */
};
const char *key, *msglog;
struct in_addr addr;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "name")) {
err = og_json_parse_string_copy(value,
repo.name,
sizeof(repo.name));
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "ip")) {
err = og_json_parse_string_copy(value,
repo.ip,
sizeof(repo.ip));
params->flags |= OG_REST_PARAM_ADDR;
} else if (!strcmp(key, "center")) {
err = og_json_parse_uint(value, &repo.center);
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_NAME |
OG_REST_PARAM_ADDR))
return -1;
if (inet_pton(AF_INET, repo.ip, &addr) <= 0) {
syslog(LOG_ERR, "invalid server ip address (%s:%d)\n",
__func__, __LINE__);
return -1;
}
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO repositorios("
"nombrerepositorio, ip, idcentro, grupoid) VALUES "
"('%s', '%s', %u, 0)",
repo.name, repo.ip, repo.center);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR,
"failed to add repository to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
og_dbi_close(dbi);
return err;
}
static int og_cmd_post_repository_delete(json_t *element,
struct og_msg_params *params)
{
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "id")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM repositorios "
"WHERE idrepositorio=%s",
params->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to delete repository from database "
"(%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows_affected(result) < 1) {
syslog(LOG_ERR, "delete did not modify any row (%s:%d)\n",
__func__, __LINE__);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
static int og_cmd_post_room_update(json_t *element,
struct og_msg_params *params)
{
struct og_room room = {};
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "name")) {
err = og_json_parse_string_copy(value, room.name,
sizeof(room.name));
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "gateway")) {
err = og_json_parse_string_copy(value, room.gateway,
sizeof(room.gateway));
params->flags |= OG_REST_PARAM_GATEWAY;
} else if (!strcmp(key, "netmask")) {
err = og_json_parse_string_copy(value, room.netmask,
sizeof(room.netmask));
params->flags |= OG_REST_PARAM_NETMASK;
} else if (!strcmp(key, "id")) {
err = og_json_parse_uint(value, &room.id);
params->flags |= OG_REST_PARAM_ROOM;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ROOM |
OG_REST_PARAM_NAME |
OG_REST_PARAM_NETMASK |
OG_REST_PARAM_GATEWAY))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT idaula, idcentro FROM aulas WHERE idaula='%u'",
room.id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (!dbi_result_next_row(result)) {
syslog(LOG_ERR, "could not find a room with that id: %u\n",
room.id);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
room.center = dbi_result_get_uint(result, "idcentro");
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"SELECT nombreaula FROM aulas "
"WHERE nombreaula='%s' AND idcentro=%d AND idaula<>'%u'",
room.name, room.center, room.id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "Room with name %s already exists in the "
"center with id %d\n",
room.name, room.center);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"UPDATE aulas"
" SET nombreaula='%s',"
" netmask='%s',"
" router='%s'"
" WHERE idaula='%u';",
room.name, room.netmask, room.gateway, room.id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to update room in database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
return 0;
}
static int og_cmd_post_room_add(json_t *element,
struct og_msg_params *params)
{
struct og_room room = {};
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "name")) {
err = og_json_parse_string_copy(value, room.name,
sizeof(room.name));
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "location")) {
err = og_json_parse_string_copy(value, room.location,
sizeof(room.location));
} else if (!strcmp(key, "gateway")) {
err = og_json_parse_string_copy(value, room.gateway,
sizeof(room.gateway));
} else if (!strcmp(key, "netmask")) {
err = og_json_parse_string_copy(value, room.netmask,
sizeof(room.netmask));
params->flags |= OG_REST_PARAM_NETMASK;
} else if (!strcmp(key, "ntp")) {
err = og_json_parse_string_copy(value, room.ntp,
sizeof(room.ntp));
} else if (!strcmp(key, "dns")) {
err = og_json_parse_string_copy(value, room.dns,
sizeof(room.dns));
} else if (!strcmp(key, "center")) {
err = og_json_parse_uint(value, &room.center);
params->flags |= OG_REST_PARAM_CENTER;
} else if (!strcmp(key, "folder_id")) {
err = og_json_parse_uint(value, &room.folder_id);
} else if (!strcmp(key, "remote")) {
err = og_json_parse_bool(value, &room.remote);
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_NAME |
OG_REST_PARAM_NETMASK |
OG_REST_PARAM_CENTER))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT nombreaula FROM aulas "
"WHERE nombreaula='%s' AND idcentro=%d",
room.name, room.center);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "Room with name %s already exists in the "
"center with id %d\n",
room.name, room.center);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO aulas("
" idcentro,"
" nombreaula,"
" netmask,"
" grupoid,"
" ubicacion,"
" router,"
" dns,"
" ntp,"
" inremotepc) VALUES ("
"%d, '%s', '%s', %d, '%s', "
"'%s', '%s', '%s', %d)",
room.center, room.name, room.netmask,
room.folder_id, room.location, room.gateway,
room.dns, room.ntp, room.remote);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to add room to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
static int og_cmd_post_room_delete(json_t *element,
struct og_msg_params *params)
{
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "id")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM aulas WHERE idaula=%s",
params->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows_affected(result) < 1) {
syslog(LOG_ERR, "delete did not modify any row (%s:%d)\n",
__func__, __LINE__);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
enum {
OG_SCHEDULE_CMD_TYPE = 0,
OG_SCHEDULE_CMD_PARAMS,
};
static bool og_cmd_validate(const struct og_cmd_json *cmd,
const uint64_t flags)
{
return (cmd->flags & flags) == flags;
}
static int og_cmd_post_schedule_command(json_t *element,
struct og_msg_params *params)
{
char *centerid_query = "SELECT o.idordenador, c.idcentro "
"FROM `ordenadores` AS o "
"INNER JOIN aulas AS a ON o.idaula = a.idaula "
"INNER JOIN centros AS c ON a.idcentro = c.idcentro "
"WHERE o.ip = '%s';";
uint32_t sequence, session = 0;
int center_id, client_id, len;
struct og_cmd_json cmd = {};
const char *legacy_params;
const char *key, *msglog;
struct og_dbi *dbi;
char task_id[128];
bool when = false;
dbi_result result;
json_t *value;
int err = 0, i;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "command")) {
err = og_json_parse_string(value, &cmd.type);
cmd.flags |= OG_SCHEDULE_CMD_TYPE;
} else if (!strcmp(key, "params")) {
cmd.json = value;
cmd.flags |= OG_SCHEDULE_CMD_PARAMS;
} else if (!strcmp(key, "when")) {
err = og_json_parse_time_params(value, params);
when = true;
}
if (err < 0)
return err;
}
if (!og_cmd_validate(&cmd, OG_SCHEDULE_CMD_TYPE |
OG_SCHEDULE_CMD_PARAMS))
return -1;
if (!when) {
params->time.check_stale = false;
og_schedule_time_now(&params->time);
params->flags |= OG_REST_PARAM_TIME_YEARS |
OG_REST_PARAM_TIME_MONTHS |
OG_REST_PARAM_TIME_WEEKS |
OG_REST_PARAM_TIME_WEEK_DAYS |
OG_REST_PARAM_TIME_DAYS |
OG_REST_PARAM_TIME_HOURS |
OG_REST_PARAM_TIME_AM_PM |
OG_REST_PARAM_TIME_MINUTES;
} else {
params->time.check_stale = true;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_TIME_YEARS |
OG_REST_PARAM_TIME_MONTHS |
OG_REST_PARAM_TIME_WEEKS |
OG_REST_PARAM_TIME_WEEK_DAYS |
OG_REST_PARAM_TIME_DAYS |
OG_REST_PARAM_TIME_HOURS |
OG_REST_PARAM_TIME_MINUTES |
OG_REST_PARAM_TIME_AM_PM))
return -1;
params->type = "command";
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
goto err_dbi_open;
}
legacy_params = og_msg_params_to_legacy(&cmd);
if (!legacy_params)
goto err_legacy_params;
/* ips_array -> ids */
for (i = 0; i < params->ips_array_len; i++) {
result = dbi_conn_queryf(dbi->conn, centerid_query, params->ips_array[i]);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
goto err_dbi_result;
}
if (dbi_result_get_numrows(result) != 1) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "client not found (%s:%d) %s\n",
__func__, __LINE__, msglog);
goto err_dbi;
}
if (!dbi_result_next_row(result)) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to get idcentro (%s:%d) %s\n",
__func__, __LINE__, msglog);
goto err_dbi;
}
center_id = dbi_result_get_uint(result, "idcentro");
if (!center_id) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to get idcentro (%s:%d) %s\n",
__func__, __LINE__, msglog);
goto err_dbi;
}
client_id = dbi_result_get_uint(result, "idordenador");
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn, "INSERT INTO acciones (idordenador, "
"idcentro, parametros)"
"VALUES (%d, %d, '%s')",
client_id, center_id, legacy_params);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
goto err_dbi_result;
}
dbi_result_free(result);
sequence = dbi_conn_sequence_last(dbi->conn, NULL);
/* This 'session' ID allows us to correlate the schedule with
* the commands after expansion.
*/
if (!session)
session = dbi_conn_sequence_last(dbi->conn, NULL);
result = dbi_conn_queryf(dbi->conn, "UPDATE acciones SET idordenador=%d, "
"idcentro=%d, parametros='%s', sesion=%d"
"WHERE idaccion=%d",
client_id, center_id, legacy_params,
session, sequence);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
goto err_dbi_result;
}
dbi_result_free(result);
}
len = snprintf(task_id, sizeof(session), "%d", session);
if (len >= (int)sizeof(task_id)) {
syslog(LOG_ERR, "truncated snprintf (%s:%d)\n",
__func__, __LINE__);
goto err_dbi_result;
}
params->task_id = task_id;
og_task_schedule_create(params);
free((char *)legacy_params);
og_dbi_close(dbi);
return 0;
err_dbi:
dbi_result_free(result);
err_dbi_result:
free((char *)legacy_params);
err_legacy_params:
og_dbi_close(dbi);
err_dbi_open:
return -1;
}
static int og_cmd_post_procedure_run(json_t *element,
struct og_msg_params *params)
{
const char *centerid_query = "SELECT o.idordenador, c.idcentro "
"FROM `ordenadores` AS o "
"INNER JOIN aulas AS a "
"ON o.idaula = a.idaula "
"INNER JOIN centros AS c "
"ON a.idcentro = c.idcentro "
"WHERE o.ip = '%s';";
struct og_task task = {};
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
int i, err = 0;
json_t *value;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "procedure")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
goto err_return;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_ID ))
goto err_return;
task.type_scope = AMBITO_ORDENADORES;
task.procedure_id = atoi(params->id);
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
goto err_return;
}
for (i = 0; i < params->ips_array_len; i++) {
result = dbi_conn_queryf(dbi->conn, centerid_query, params->ips_array[i]);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
goto err_close_dbi;
}
if (dbi_result_get_numrows(result) != 1 ||
!dbi_result_next_row(result) ||
!dbi_result_get_uint(result, "idcentro") ||
!dbi_result_get_uint(result, "idordenador")) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to get query data (%s:%d) %s\n",
__func__, __LINE__, msglog);
goto err_free_result;
}
task.center_id = dbi_result_get_uint(result, "idcentro");
task.scope = dbi_result_get_uint(result, "idordenador");
dbi_result_free(result);
if (og_dbi_queue_procedure(dbi, &task))
goto err_close_dbi;
}
og_dbi_close(dbi);
return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
NULL);
err_free_result:
dbi_result_free(result);
err_close_dbi:
og_dbi_close(dbi);
err_return:
return -1;
}
static int og_cmd_get_servers(char *buffer_reply)
{
json_t *root, *servers, *address;
struct og_buffer og_buffer = {
.data = buffer_reply,
};
char ipaddr[50] = {};
struct og_dbi *dbi;
dbi_result result;
int id, ret;
root = json_object();
if (!root)
return -1;
servers = json_array();
if (!servers) {
json_decref(root);
return -1;
}
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
json_decref(root);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT identorno, ipserveradm "
"FROM entornos");
while (dbi_result_next_row(result)) {
address = json_object();
id = dbi_result_get_int(result, "identorno");
snprintf(ipaddr, sizeof(ipaddr), "%s",
dbi_result_get_string(result, "ipserveradm"));
json_object_set_new(address, "id", json_integer(id));
json_object_set_new(address, "address", json_string(ipaddr));
json_array_append_new(servers, address);
}
json_object_set_new(root, "servers", servers);
dbi_result_free(result);
og_dbi_close(dbi);
ret = json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII);
json_decref(root);
return ret;
}
static int og_cmd_post_server(json_t *element,
struct og_msg_params *params,
char *buffer_reply)
{
struct og_buffer og_buffer = {
.data = buffer_reply,
};
const char *key, *msglog;
json_t *value, *root;
int err = 0, id, ret;
struct in_addr addr;
struct og_dbi *dbi;
dbi_result result;
json_object_foreach(element, key, value) {
if (!strcmp(key, "address")) {
err = og_json_parse_string(value, &params->name);
params->flags |= OG_REST_PARAM_NAME;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_NAME))
return -1;
if (inet_pton(AF_INET, params->name, &addr) <= 0) {
syslog(LOG_ERR, "invalid server ip address (%s:%d)\n",
__func__, __LINE__);
return -1;
}
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT identorno FROM entornos WHERE ipserveradm='%s'",
params->name);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows(result) > 0) {
syslog(LOG_ERR, "Address %s already exists\n",
params->name);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO entornos("
" ipserveradm,"
" protoclonacion) VALUES ("
"'%s', 'UNICAST')",
params->name);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to add new ogserver address to database (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
root = json_object();
if (!root) {
syslog(LOG_ERR, "Cannot allocate JSON object (%s:%d)\n",
__func__, __LINE__);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
id = dbi_conn_sequence_last(dbi->conn, NULL);
json_object_set_new(root, "id", json_integer(id));
ret = json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII);
json_decref(root);
dbi_result_free(result);
og_dbi_close(dbi);
return ret;
}
static int og_cmd_delete_server(json_t *element,
struct og_msg_params *params)
{
const char *key, *msglog;
struct og_dbi *dbi;
dbi_result result;
json_t *value;
int err = 0;
json_object_foreach(element, key, value) {
if (!strcmp(key, "id")) {
err = og_json_parse_string(value, &params->id);
params->flags |= OG_REST_PARAM_ID;
}
if (err < 0)
return err;
}
if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"DELETE FROM entornos WHERE identorno='%s'",
params->id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to delete server (%s:%d) %s\n",
__func__, __LINE__, msglog);
og_dbi_close(dbi);
return -1;
}
if (dbi_result_get_numrows_affected(result) < 1) {
syslog(LOG_ERR, "delete did not modify any row (%s:%d)\n",
__func__, __LINE__);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
static int og_dbi_update_oglive(struct og_dbi *dbi, const char *mac,
const char * oglive)
{
const char *msglog;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"UPDATE ordenadores SET oglivedir='%s' "
"WHERE mac='%s'",
oglive, mac);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
static int og_cmd_oglive_set(json_t *element, struct og_msg_params *params)
{
char ips_str[(OG_DB_IP_MAXLEN + 1) * OG_CLIENTS_MAX + 1] = {};
const char legacy_default_oglive_str[] = "ogLive";
const char *oglive_str, *mac, *mode_str;
int ips_str_len = 0;
struct og_dbi *dbi;
uint64_t flags = 0;
dbi_result result;
const char *key;
json_t *value;
int err = 0;
int i;
json_object_foreach(element, key, value) {
if (!strcmp(key, "clients")) {
err = og_json_parse_clients(value, params);
} else if (!strcmp(key, "name")) {
err = og_json_parse_string(value, &oglive_str);
flags |= OG_REST_PARAM_NAME;
} else {
err = -1;
}
if (err < 0)
return err;
}
if (!og_flags_validate(flags, OG_REST_PARAM_NAME) ||
!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
return -1;
if (!strcmp(oglive_str, "default"))
oglive_str = legacy_default_oglive_str;
for (i = 0; i < params->ips_array_len; ++i) {
ips_str_len += snprintf(ips_str + ips_str_len,
sizeof(ips_str) - ips_str_len,
"'%s',", params->ips_array[i]);
}
ips_str[ips_str_len - 1] = '\0';
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT mac, arranque FROM ordenadores "
"WHERE ip IN (%s)", ips_str);
while (dbi_result_next_row(result)) {
mac = dbi_result_get_string(result, "mac");
mode_str = dbi_result_get_string(result, "arranque");
err = og_dbi_update_oglive(dbi, mac, oglive_str);
if (err != 0) {
syslog(LOG_ERR, "failed to change db oglive (%s:%d)\n",
__func__, __LINE__);
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
err = og_set_client_mode(dbi, mac, mode_str);
if (err != 0) {
dbi_result_free(result);
og_dbi_close(dbi);
return -1;
}
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
static int og_cmd_get_server_stats(char *buffer_reply)
{
json_t *root, *time_obj, *memory, *swap;
struct og_buffer og_buffer = {
.data = buffer_reply
};
struct sysinfo stats;
time_t now;
sysinfo(&stats);
root = json_object();
if (!root)
return -1;
time_obj = json_object();
if (!time_obj) {
json_decref(root);
return -1;
}
memory = json_object();
if (!memory) {
json_decref(root);
json_decref(time_obj);
return -1;
}
swap = json_object();
if (!swap) {
json_decref(root);
json_decref(time_obj);
json_decref(memory);
return -1;
}
now = time(NULL);
json_object_set_new(time_obj, "now", json_integer(now));
json_object_set_new(time_obj, "boot", json_integer(stats.uptime));
json_object_set_new(time_obj, "start", json_integer(now - start_time));
json_object_set_new(root, "time", time_obj);
json_object_set_new(memory, "size", json_integer(stats.totalram));
json_object_set_new(memory, "free", json_integer(stats.freeram));
json_object_set_new(root, "memory", memory);
json_object_set_new(swap, "size", json_integer(stats.totalswap));
json_object_set_new(swap, "free", json_integer(stats.freeswap));
json_object_set_new(root, "swap", swap);
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
json_decref(root);
return -1;
}
json_decref(root);
return 0;
}
static int og_client_method_not_found(struct og_client *cli)
{
/* To meet RFC 7231, this function MUST generate an Allow header field
* containing the correct methods. For example: "Allow: POST\r\n"
*/
char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n"
"Content-Length: 0\r\n\r\n";
send(og_client_socket(cli), buf, strlen(buf), 0);
return -1;
}
static int og_client_bad_request(struct og_client *cli)
{
char buf[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n";
send(og_client_socket(cli), buf, strlen(buf), 0);
return -1;
}
static int og_client_not_found(struct og_client *cli)
{
char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
send(og_client_socket(cli), buf, strlen(buf), 0);
return -1;
}
static int og_client_not_authorized(struct og_client *cli)
{
char buf[] = "HTTP/1.1 401 Unauthorized\r\n"
"WWW-Authenticate: Basic\r\n"
"Content-Length: 0\r\n\r\n";
send(og_client_socket(cli), buf, strlen(buf), 0);
return -1;
}
static int og_server_internal_error(struct og_client *cli)
{
char buf[] = "HTTP/1.1 500 Internal Server Error\r\n"
"Content-Length: 0\r\n\r\n";
send(og_client_socket(cli), buf, strlen(buf), 0);
return -1;
}
static int og_client_ok(struct og_client *cli, char *buf_reply)
{
char buf[OG_MSG_RESPONSE_MAXLEN] = {};
int len;
len = snprintf(buf, sizeof(buf),
"HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s",
strlen(buf_reply), buf_reply);
if (len >= (int)sizeof(buf)) {
syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n",
inet_ntoa(cli->addr.sin_addr),
ntohs(cli->addr.sin_port));
return og_server_internal_error(cli);
}
send(og_client_socket(cli), buf, strlen(buf), 0);
return 0;
}
static const char *og_method_str[] = {
[OG_METHOD_GET] = "GET",
[OG_METHOD_POST] = "POST",
[OG_METHOD_DELETE] = "DELETE",
[OG_METHOD_NO_HTTP] = "NOHTTP",
};
static const char *og_method(enum og_rest_method method)
{
if (method > OG_METHOD_NO_HTTP)
return "UNKNOWN";
return og_method_str[method];
}
struct {
const char *uri;
} og_uri_handler[] = {
[OG_URI_UNKNOWN] = { "unknown", },
[OG_URI_CLIENTS] = { "clients", },
[OG_URI_CLIENT_REPO] = { "client/repo", },
[OG_URI_CLIENT_SETUP] = { "client/setup", },
[OG_URI_CLIENT_SERVER] = { "client/server", },
[OG_URI_CLIENT_INFO] = { "client/info", },
[OG_URI_CLIENT_ADD] = { "client/add", },
[OG_URI_CLIENT_UPDATE] = { "client/update", },
[OG_URI_CLIENT_DELETE] = { "client/delete", },
[OG_URI_CLIENT_MOVE] = { "client/move", },
[OG_URI_WOL] = { "wol", },
[OG_URI_SHELL_RUN] = { "shell/run", },
[OG_URI_SHELL_OUTPUT] = { "shell/output", },
[OG_URI_SHELL_LIST] = { "shell/list", },
[OG_URI_SESSION] = { "session", },
[OG_URI_SCOPES] = { "scopes", },
[OG_URI_POWEROFF] = { "poweroff", },
[OG_URI_REBOOT] = { "reboot", },
[OG_URI_BOOT_MODE] = { "mode", },
[OG_URI_STOP] = { "stop", },
[OG_URI_REFRESH] = { "refresh", },
[OG_URI_HARDWARE] = { "hardware", },
[OG_URI_SOFTWARE] = { "software", },
[OG_URI_REPO] = { "repositories", },
[OG_URI_REPO_ADD] = { "repository/add", },
[OG_URI_REPO_UPDATE] = { "repository/update", },
[OG_URI_REPO_DELETE] = { "repository/delete", },
[OG_URI_IMAGES] = { "images", },
[OG_URI_IMAGE_CREATE] = { "image/create" },
[OG_URI_IMAGE_UPDATE] = { "image/update" },
[OG_URI_IMAGE_RESTORE] = { "image/restore", },
[OG_URI_IMAGE_DELETE] = { "image/delete", },
[OG_URI_IMAGE_RESTRICT] = { "image/restrict", },
[OG_URI_CACHE_LIST] = { "cache/list", },
[OG_URI_CACHE_DELETE] = { "cache/delete", },
[OG_URI_PART_SETUP] = { "setup", },
[OG_URI_RUN_SCHEDULE] = { "run/schedule", },
[OG_URI_TASK_RUN] = { "task/run", },
[OG_URI_SCHEDULE_CREATE] = { "schedule/create", },
[OG_URI_SCHEDULE_DELETE] = { "schedule/delete", },
[OG_URI_SCHEDULE_UPDATE] = { "schedule/update", },
[OG_URI_SCHEDULE_GET] = { "schedule/get", },
[OG_URI_OGLIVE_LIST] = { "oglive/list", },
[OG_URI_OGLIVE_SET] = { "oglive/set", },
[OG_URI_CENTER_ADD] = { "center/add", },
[OG_URI_CENTER_UPDATE] = { "center/update", },
[OG_URI_CENTER_DELETE] = { "center/delete", },
[OG_URI_CENTER_INFO] = { "center/info", },
[OG_URI_ROOM_ADD] = { "room/add", },
[OG_URI_ROOM_UPDATE] = { "room/update", },
[OG_URI_ROOM_DELETE] = { "room/delete", },
[OG_URI_ROOM_INFO] = { "room/info", },
[OG_URI_PROC_ADD] = { "procedure/add", },
[OG_URI_PROC_UPDATE] = { "procedure/update", },
[OG_URI_PROC_RUN] = { "procedure/run", },
[OG_URI_SCHEDULE_RUN] = { "schedule/command", },
[OG_URI_PROC_DEL] = { "procedure/delete", },
[OG_URI_TASK_ADD] = { "task/add", },
[OG_URI_SERVER] = { "server", },
[OG_URI_STATS] = { "stats", },
[OG_URI_FOLDER_ADD] = { "folder/add", },
[OG_URI_FOLDER_UPDATE] = { "folder/update", },
[OG_URI_FOLDER_DELETE] = { "folder/delete", },
};
static const char *og_uri(enum og_rest_uri uri)
{
if (uri >= OG_URI_MAX)
return "unknown";
return og_uri_handler[uri].uri;
}
static enum og_rest_uri og_str_to_uri(const char *uri)
{
int i;
for (i = 0; i < OG_URI_MAX; i++) {
if (!strncmp(og_uri_handler[i].uri, uri,
strlen(og_uri_handler[i].uri)))
return i;
}
return OG_URI_UNKNOWN;
}
static void og_rest_log(const struct og_client *cli, enum og_rest_method method,
enum og_rest_uri uri, const struct og_msg_params *params)
{
char log_buf[(16 * OG_CLIENTS_MAX) + 4096] = {};
int i, ret;
switch (uri) {
case OG_URI_SCOPES:
case OG_URI_CLIENTS:
/* very spammy, do not log these. */
return;
default:
break;
}
ret = snprintf(log_buf, sizeof(log_buf), "%s:%hu %s /%s ",
inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
og_method(method), og_uri(uri));
if (params->ips_array_len > 0) {
ret += snprintf(&log_buf[ret], sizeof(log_buf) - ret, "clients=");
if (ret > sizeof(log_buf))
return;
for (i = 0; i < params->ips_array_len - 1; i++) {
ret += snprintf(&log_buf[ret], sizeof(log_buf) - ret,
"%s,", params->ips_array[i]);
if (ret > sizeof(log_buf))
return;
}
ret += snprintf(&log_buf[ret], sizeof(log_buf) - ret, "%s", params->ips_array[i]);
if (ret > sizeof(log_buf))
return;
}
syslog(LOG_INFO, "%s", log_buf);
}
int og_client_state_process_payload_rest(struct og_client *cli)
{
char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {};
struct og_msg_params params = {};
enum og_rest_method method;
const char *cmd, *body;
json_error_t json_err;
enum og_rest_uri uri;
json_t *root = NULL;
int err = 0;
if (!strncmp(cli->buf, "GET", strlen("GET"))) {
method = OG_METHOD_GET;
cmd = cli->buf + strlen("GET") + 2;
} else if (!strncmp(cli->buf, "POST", strlen("POST"))) {
method = OG_METHOD_POST;
cmd = cli->buf + strlen("POST") + 2;
} else if (!strncmp(cli->buf, "DELETE", strlen("DELETE"))) {
method = OG_METHOD_DELETE;
cmd = cli->buf + strlen("DELETE") + 2;
} else
return og_client_method_not_found(cli);
body = strstr(cli->buf, "\r\n\r\n") + 4;
if (strcmp(cli->auth_token, ogconfig.rest.api_token)) {
syslog(LOG_ERR, "wrong Authentication key\n");
return og_client_not_authorized(cli);
}
if (cli->content_length) {
root = json_loads(body, 0, &json_err);
if (!root) {
syslog(LOG_ERR, "malformed json line %d: %s\n",
json_err.line, json_err.text);
return og_client_not_found(cli);
}
}
uri = og_str_to_uri(cmd);
if (!strncmp(cmd, "clients", strlen("clients"))) {
if (method != OG_METHOD_POST &&
method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (method == OG_METHOD_POST && !root) {
syslog(LOG_ERR, "command clients with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
switch (method) {
case OG_METHOD_POST:
err = og_cmd_post_clients(root, &params);
break;
case OG_METHOD_GET:
err = og_cmd_get_clients(root, &params, buf_reply);
break;
default:
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
} else if (!strncmp(cmd, "client/repo", strlen("client/repo"))) {
switch (method) {
case OG_METHOD_POST:
if (!root) {
syslog(LOG_ERR, "client post repo command with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_client_repo(root, &params, buf_reply);
break;
default:
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
} else if (!strncmp(cmd, "client/setup",
strlen("client/setup"))) {
if (method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command client partitions with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_get_client_setup(root, &params, buf_reply);
} else if (!strncmp(cmd, "client/server", strlen("client/server"))) {
switch (method) {
case OG_METHOD_POST:
if (!root) {
syslog(LOG_ERR, "client post server command with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_client_server(root, &params, buf_reply);
break;
default:
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
} else if (!strncmp(cmd, "client/info",
strlen("client/info"))) {
if (method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command client info with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_get_client_info(root, &params, buf_reply);
} else if (!strncmp(cmd, "client/add", strlen("client/add"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command client info with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_client_add(root, &params, buf_reply);
} else if (!strncmp(cmd, "client/update", strlen("client/update"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command client info with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_client_update(root, &params, buf_reply);
} else if (!strncmp(cmd, "client/delete", strlen("client/delete"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command client delete with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_client_delete(root, &params);
} else if (!strncmp(cmd, "client/move", strlen("client/move"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command client move with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_client_move(root, &params);
} else if (!strncmp(cmd, "folder/add", strlen("folder/add"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command folder add with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_folder_add(root, &params);
} else if (!strncmp(cmd, "folder/update", strlen("folder/update"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command folder update with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_folder_update(root, &params);
} else if (!strncmp(cmd, "folder/delete", strlen("folder/delete"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command folder delete with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_folder_delete(root, &params);
} else if (!strncmp(cmd, "wol", strlen("wol"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command wol with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_wol(root, &params);
} else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command run with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_run_post(root, &params);
} else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) {
if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command output with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_run_get(root, &params, buf_reply);
} else if (!strncmp(cmd, "shell/list", strlen("shell/list"))) {
if (method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
err = og_cmd_shell_list(buf_reply);
} else if (!strncmp(cmd, "session", strlen("session"))) {
if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command session with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
if (method == OG_METHOD_POST)
err = og_cmd_session(root, &params);
else
err = og_cmd_get_session(root, &params, buf_reply);
} else if (!strncmp(cmd, "scopes", strlen("scopes"))) {
if (method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (root) {
syslog(LOG_ERR, "command scopes with payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_scope_get(root, &params, buf_reply);
} else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command poweroff with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_poweroff(root, &params);
} else if (!strncmp(cmd, "reboot", strlen("reboot"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command reboot with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_reboot(root, &params);
} else if (!strncmp(cmd, "mode", strlen("mode"))) {
if (method != OG_METHOD_GET && method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (method == OG_METHOD_POST && !root) {
syslog(LOG_ERR, "command mode with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
if (method == OG_METHOD_GET)
err = og_cmd_get_modes(root, &params, buf_reply);
else if (method == OG_METHOD_POST)
err = og_cmd_post_modes(root, &params);
} else if (!strncmp(cmd, "stop", strlen("stop"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command stop with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_stop(root, &params);
} else if (!strncmp(cmd, "refresh", strlen("refresh"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command refresh with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_refresh(root, &params);
} else if (!strncmp(cmd, "hardware", strlen("hardware"))) {
if (method != OG_METHOD_GET && method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command hardware with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
if (method == OG_METHOD_GET)
err = og_cmd_get_hardware(root, &params, buf_reply);
else if (method == OG_METHOD_POST)
err = og_cmd_hardware(root, &params);
} else if (!strncmp(cmd, "software", strlen("software"))) {
if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command software with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
if (method == OG_METHOD_POST)
err = og_cmd_software(root, &params);
else
err = og_cmd_get_software(root, &params, buf_reply);
} else if (!strncmp(cmd, "repositories", strlen("repositories"))) {
if (method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (root) {
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_get_repositories(buf_reply);
} else if (!strncmp(cmd, "repository/add", strlen("repository/add"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command repository add with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_repository_add(root, &params, buf_reply);
} else if (!strncmp(cmd, "repository/update", strlen("repository/update"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command repository add with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_repository_update(root, &params, buf_reply);
} else if (!strncmp(cmd, "repository/delete",
strlen("repository/delete"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command repository delete with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_repository_delete(root, &params);
} else if (!strncmp(cmd, "images", strlen("images"))) {
if (method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (root) {
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_images(buf_reply);
} else if (!strncmp(cmd, "image/create", strlen("image/create"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command create with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_create_image(root, &params);
} else if (!strncmp(cmd, "image/update", strlen("image/update"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command create with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_update_image(root, &params);
} else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command create with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_restore_image(root, &params);
} else if (!strncmp(cmd, "image/delete", strlen("image/delete"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command image delete with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_delete_image(root, &params);
} else if (!strncmp(cmd, "image/restrict", strlen("image/restrict"))) {
if (!root) {
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
switch (method) {
case OG_METHOD_GET:
err = og_cmd_image_scope_list(root, &params, buf_reply);
break;
case OG_METHOD_POST:
err = og_cmd_image_scope_update(root, &params);
break;
default:
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
} else if (!strncmp(cmd, "cache/list", strlen("cache/list"))) {
if (method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command cache list with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_cache_list(root, &params, buf_reply);
} else if (!strncmp(cmd, "cache/delete", strlen("cache/delete"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command cache list with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_cache_delete(root, &params, buf_reply);
} else if (!strncmp(cmd, "setup", strlen("setup"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command create with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_setup(root, &params);
} else if (!strncmp(cmd, "run/schedule", strlen("run/schedule"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command create with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_run_schedule(root, &params);
} else if (!strncmp(cmd, "task/run", strlen("task/run"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command task with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_task_post(root, &params);
} else if (!strncmp(cmd, "schedule/create",
strlen("schedule/create"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command task with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_schedule_create(root, &params);
} else if (!strncmp(cmd, "schedule/delete",
strlen("schedule/delete"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command task with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_schedule_delete(root, &params);
} else if (!strncmp(cmd, "schedule/update",
strlen("schedule/update"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command task with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_schedule_update(root, &params);
} else if (!strncmp(cmd, "schedule/get",
strlen("schedule/get"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
err = og_cmd_schedule_get(root, &params, buf_reply);
} else if (!strncmp(cmd, "oglive/list",
strlen("oglive/list"))) {
if (method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
err = og_cmd_oglive_list(buf_reply);
} else if (!strncmp(cmd, "oglive/set", strlen("oglive/set"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command oglive set with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_oglive_set(root, &params);
} else if (!strncmp(cmd, "center/add",
strlen("center/add"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_center_add(root, &params, buf_reply);
} else if (!strncmp(cmd, "center/delete", strlen("center/delete"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command center delete with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_center_delete(root, &params);
} else if (!strncmp(cmd, "center/info",
strlen("center/info"))) {
if (method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command client info with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_get_center_info(root, &params, buf_reply);
} else if (!strncmp(cmd, "center/update", strlen("center/update"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command center update with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_center_update(root, &params);
} else if (!strncmp(cmd, "room/add",
strlen("room/add"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command task with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_room_add(root, &params);
} else if (!strncmp(cmd, "room/update",
strlen("room/update"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR, "command task with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_room_update(root, &params);
} else if (!strncmp(cmd, "room/delete", strlen("room/delete"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command room delete with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_room_delete(root, &params);
} else if (!strncmp(cmd, "room/info", strlen("room/info"))) {
if (method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command room info with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_get_room_info(root, &params, buf_reply);
} else if (!strncmp(cmd, "procedure/add", strlen("procedure/add"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command procedure add with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_procedure_add(root, &params);
} else if (!strncmp(cmd, "procedure/update",
strlen("procedure/update"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command procedure update with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_procedure_update(root, &params);
} else if (!strncmp(cmd, "procedure/run", strlen("procedure/run"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command procedure run with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_procedure_run(root, &params);
} else if (!strncmp(cmd, "schedule/command", strlen("schedule/command"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command schedule action with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_schedule_command(root, &params);
} else if (!strncmp(cmd, "procedure/delete", strlen("schedule/command"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command procedure delete with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_procedure_delete(root, &params);
} else if (!strncmp(cmd, "task/add", strlen("task/add"))) {
if (method != OG_METHOD_POST) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command task add with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_task_add(root, &params);
} else if (!strncmp(cmd, "server", strlen("server"))) {
switch (method) {
case OG_METHOD_GET:
err = og_cmd_get_servers(buf_reply);
break;
case OG_METHOD_DELETE:
err = og_cmd_delete_server(root, &params);
break;
case OG_METHOD_POST:
if (!root) {
syslog(LOG_ERR, "address add command with no payload\n");
err = og_client_bad_request(cli);
goto err_process_rest_payload;
}
err = og_cmd_post_server(root, &params, buf_reply);
break;
default:
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
} else if (!strncmp(cmd, "stats", strlen("stats"))) {
if (method != OG_METHOD_GET) {
err = og_client_method_not_found(cli);
goto err_process_rest_payload;
}
err = og_cmd_get_server_stats(buf_reply);
} else {
syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd);
err = og_client_not_found(cli);
}
og_rest_log(cli, method, uri, &params);
json_decref(root);
if (err < 0)
return og_client_bad_request(cli);
return og_client_ok(cli, buf_reply);
err_process_rest_payload:
syslog(LOG_ERR, "%s:%hu %.32s ...\n",
inet_ntoa(cli->addr.sin_addr),
ntohs(cli->addr.sin_port), cli->buf);
json_decref(root);
return err;
}