source: ogServer-Git/src/client.c @ 25e21f4

Last change on this file since 25e21f4 was 25e21f4, checked in by Javier Sánchez Parra <jsanchez@…>, 2 years ago

Log ogClient sessions in ogagent.log

Otherwise, administrators can not read the logging history from
WebConsole?.

  • Property mode set to 100644
File size: 22.3 KB
Line 
1/*
2 * Copyright (C) 2020-2021 Soleta Networks <info@soleta.eu>
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Affero General Public License as published by the
6 * Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 */
9
10#include "ogAdmServer.h"
11#include "cfg.h"
12#include "dbi.h"
13#include "utils.h"
14#include "list.h"
15#include "rest.h"
16#include "json.h"
17#include "schedule.h"
18#include <syslog.h>
19#include <sys/ioctl.h>
20#include <ifaddrs.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <jansson.h>
25#include <time.h>
26
27#define OG_LEGACY_OGAGENT_LOG_FILE "/opt/opengnsys/log/ogagent.log"
28#define OG_CLIENT_SESSION_EVENT_LOGIN "logged in"
29#define OG_CLIENT_SESSION_EVENT_LOGOUT "logged out"
30#define OG_CLIENT_SESSION_OS_LINUX "Linux"
31#define OG_CLIENT_SESSION_OS_WINDOWS "Windows"
32#define OG_CLIENT_SESSION_TIMEDATE_LEN 20
33
34static void og_status_session_log(const struct og_client *cli,
35                                  const char *type, const char* user,
36                                  const char *os)
37{
38        char date[OG_CLIENT_SESSION_TIMEDATE_LEN];
39        char client_ip[INET_ADDRSTRLEN];
40        time_t now;
41        FILE *fp;
42
43        time(&now);
44        strftime(date, OG_CLIENT_SESSION_TIMEDATE_LEN, "%FT%T", gmtime(&now));
45
46        inet_ntop(AF_INET, &(cli->addr.sin_addr), client_ip, INET_ADDRSTRLEN);
47
48        fp = fopen(OG_LEGACY_OGAGENT_LOG_FILE, "a");
49        if (fp) {
50                fprintf(fp, "%s: User %s: ip=%s, user=%s, lang=en, os=%s:%s.\n",
51                        date, type, client_ip, user, os, os);
52                fclose(fp);
53        }
54}
55
56static int og_status_session_start(struct og_client *cli, const char *user)
57{
58        switch (cli->status) {
59        case OG_CLIENT_STATUS_LINUX:
60                cli->status = OG_CLIENT_STATUS_LINUX_SESSION;
61                og_status_session_log(cli, OG_CLIENT_SESSION_EVENT_LOGIN, user,
62                                      OG_CLIENT_SESSION_OS_LINUX);
63                break;
64        case OG_CLIENT_STATUS_WIN:
65                cli->status = OG_CLIENT_STATUS_WIN_SESSION;
66                og_status_session_log(cli, OG_CLIENT_SESSION_EVENT_LOGIN, user,
67                                      OG_CLIENT_SESSION_OS_WINDOWS);
68                break;
69        default:
70                syslog(LOG_ERR, "%s:%d: invalid session start for status %d\n",
71                       __FILE__, __LINE__, cli->status);
72                return -1;
73        }
74        return 0;
75}
76
77static int og_status_session_stop(struct og_client *cli, const char *user)
78{
79        switch (cli->status) {
80        case OG_CLIENT_STATUS_WIN_SESSION:
81                cli->status = OG_CLIENT_STATUS_WIN;
82                og_status_session_log(cli, OG_CLIENT_SESSION_EVENT_LOGOUT, user,
83                                      OG_CLIENT_SESSION_OS_WINDOWS);
84                break;
85        case OG_CLIENT_STATUS_LINUX_SESSION:
86                cli->status = OG_CLIENT_STATUS_LINUX;
87                og_status_session_log(cli, OG_CLIENT_SESSION_EVENT_LOGOUT, user,
88                                      OG_CLIENT_SESSION_OS_LINUX);
89                break;
90        default:
91                syslog(LOG_ERR, "%s:%d: invalid session stop for status %d\n",
92                       __FILE__, __LINE__, cli->status);
93                return -1;
94        }
95        return 0;
96}
97
98static int og_resp_early_hints(struct og_client *cli, json_t *data)
99{
100        const char *event, *action, *user;
101        const char *key;
102        json_t *value;
103        int err = 0;
104
105        if (json_typeof(data) != JSON_OBJECT)
106                return -1;
107
108        json_object_foreach(data, key, value) {
109                if (!strcmp(key, "event")) {
110                        err = og_json_parse_string(value, &event);
111                        if (err < 0)
112                                return err;
113                } else if (!strcmp(key, "action")) {
114                        err = og_json_parse_string(value, &action);
115                        if (err < 0)
116                                return err;
117                } else if (!strcmp(key, "user")) {
118                        err = og_json_parse_string(value, &user);
119                        if (err < 0)
120                                return err;
121                }
122        }
123
124        syslog(LOG_INFO, "Received event %s %s %s\n", event, action, user);
125
126        if (strncmp(event, "session", strlen("session")))
127                return -1;
128
129        if (!strncmp(action, "start", strlen("start")))
130                return og_status_session_start(cli, user);
131        if (!strncmp(action, "stop", strlen("stop")))
132                return og_status_session_stop(cli, user);
133
134        syslog(LOG_ERR, "Invalid action for event %s %s %s\n", event, action, user);
135        return -1;
136}
137
138static int og_resp_probe(struct og_client *cli, json_t *data)
139{
140        const char *status = NULL;
141        const char *key;
142        uint32_t speed;
143        json_t *value;
144        int err = 0;
145
146        if (json_typeof(data) != JSON_OBJECT)
147                return -1;
148
149        json_object_foreach(data, key, value) {
150                if (!strcmp(key, "status")) {
151                        err = og_json_parse_string(value, &status);
152                        if (err < 0)
153                                return err;
154                } else if (!strcmp(key, "speed")) {
155                        err = og_json_parse_uint(value, &speed);
156                        if (err < 0)
157                                return err;
158                        cli->speed = speed;
159                }
160        }
161
162        if (!strcmp(status, "BSY"))
163                cli->status = OG_CLIENT_STATUS_BUSY;
164        else if (!strcmp(status, "OPG"))
165                cli->status = OG_CLIENT_STATUS_OGLIVE;
166        else if (!strcmp(status, "VDI"))
167                cli->status = OG_CLIENT_STATUS_VIRTUAL;
168
169        return status ? 0 : -1;
170}
171
172static int og_resp_shell_run(struct og_client *cli, json_t *data)
173{
174        const char *output = NULL;
175        const char *key;
176        json_t *value;
177        int err = -1;
178
179        if (json_typeof(data) != JSON_OBJECT)
180                return -1;
181
182        json_object_foreach(data, key, value) {
183                if (!strcmp(key, "out")) {
184                        err = og_json_parse_string(value, &output);
185                        if (err < 0)
186                                return err;
187                }
188        }
189
190        if (!output) {
191                syslog(LOG_ERR, "%s:%d: malformed json response\n",
192                       __FILE__, __LINE__);
193                return -1;
194        }
195
196        free((void *)cli->shell_output);
197        cli->shell_output = strdup(output);
198
199        return 0;
200}
201
202struct og_computer_legacy  {
203        char center[OG_DB_INT_MAXLEN + 1];
204        char id[OG_DB_INT_MAXLEN + 1];
205        char hardware[8192];
206};
207
208static int og_resp_hardware(json_t *data, struct og_client *cli)
209{
210        struct og_computer_legacy legacy = {};
211        struct og_computer computer = {};
212        const char *hardware = NULL;
213        struct og_dbi *dbi;
214        const char *key;
215        json_t *value;
216        int err = 0;
217        bool res;
218
219        if (json_typeof(data) != JSON_OBJECT)
220                return -1;
221
222        json_object_foreach(data, key, value) {
223                if (!strcmp(key, "hardware")) {
224                        err = og_json_parse_string(value, &hardware);
225                        if (err < 0)
226                                return -1;
227                }
228        }
229
230        if (!hardware) {
231                syslog(LOG_ERR, "malformed response json\n");
232                return -1;
233        }
234
235        dbi = og_dbi_open(&ogconfig.db);
236        if (!dbi) {
237                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
238                       __func__, __LINE__);
239                return -1;
240        }
241
242        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
243        if (err < 0) {
244                og_dbi_close(dbi);
245                return -1;
246        }
247
248        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
249        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
250        snprintf(legacy.hardware, sizeof(legacy.hardware), "%s", hardware);
251
252        res = actualizaHardware(dbi, legacy.hardware, legacy.id, computer.name,
253                                legacy.center);
254        og_dbi_close(dbi);
255
256        if (!res) {
257                syslog(LOG_ERR, "Problem updating client configuration\n");
258                return -1;
259        }
260
261        return 0;
262}
263
264struct og_software_legacy {
265        char software[8192];
266        char center[OG_DB_INT_MAXLEN + 1];
267        char part[OG_DB_SMALLINT_MAXLEN + 1];
268        char id[OG_DB_INT_MAXLEN + 1];
269};
270
271static int og_resp_software(json_t *data, struct og_client *cli)
272{
273        struct og_software_legacy legacy = {};
274        struct og_computer computer = {};
275        const char *partition = NULL;
276        const char *software = NULL;
277        struct og_dbi *dbi;
278        const char *key;
279        json_t *value;
280        int err = 0;
281        bool res;
282
283        if (json_typeof(data) != JSON_OBJECT)
284                return -1;
285
286        json_object_foreach(data, key, value) {
287                if (!strcmp(key, "software"))
288                        err = og_json_parse_string(value, &software);
289                else if (!strcmp(key, "partition"))
290                        err = og_json_parse_string(value, &partition);
291
292                if (err < 0)
293                        return -1;
294        }
295
296        if (!software || !partition) {
297                syslog(LOG_ERR, "malformed response json\n");
298                return -1;
299        }
300
301        dbi = og_dbi_open(&ogconfig.db);
302        if (!dbi) {
303                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
304                       __func__, __LINE__);
305                return -1;
306        }
307
308        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
309        if (err < 0) {
310                og_dbi_close(dbi);
311                return -1;
312        }
313
314        snprintf(legacy.software, sizeof(legacy.software), "%s", software);
315        snprintf(legacy.part, sizeof(legacy.part), "%s", partition);
316        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
317        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
318
319        res = actualizaSoftware(dbi, legacy.software, legacy.part, legacy.id,
320                                computer.name, legacy.center);
321        og_dbi_close(dbi);
322
323        if (!res) {
324                syslog(LOG_ERR, "Problem updating client configuration\n");
325                return -1;
326        }
327
328        return 0;
329}
330
331#define OG_PARAMS_RESP_REFRESH  (OG_PARAM_PART_DISK |           \
332                                 OG_PARAM_PART_NUMBER |         \
333                                 OG_PARAM_PART_CODE |           \
334                                 OG_PARAM_PART_FILESYSTEM |     \
335                                 OG_PARAM_PART_OS |             \
336                                 OG_PARAM_PART_SIZE |           \
337                                 OG_PARAM_PART_USED_SIZE)
338
339static int og_json_parse_partition_array(json_t *value,
340                                         struct og_partition *partitions)
341{
342        json_t *element;
343        int i, err;
344
345        if (json_typeof(value) != JSON_ARRAY)
346                return -1;
347
348        for (i = 0; i < json_array_size(value) && i < OG_PARTITION_MAX; i++) {
349                element = json_array_get(value, i);
350
351                err = og_json_parse_partition(element, &partitions[i],
352                                              OG_PARAMS_RESP_REFRESH);
353                if (err < 0)
354                        return err;
355        }
356
357        return 0;
358}
359
360static int og_dbi_queue_autorun(uint32_t computer_id, uint32_t proc_id)
361{
362        struct og_task dummy_task = {
363                .scope          = computer_id,
364                .type_scope     = AMBITO_ORDENADORES,
365                .procedure_id   = proc_id,
366        };
367        struct og_dbi *dbi;
368
369        dbi = og_dbi_open(&ogconfig.db);
370        if (!dbi) {
371                syslog(LOG_ERR, "cannot open connection database "
372                                "(%s:%d)\n", __func__, __LINE__);
373                return -1;
374        }
375        if (og_dbi_queue_procedure(dbi, &dummy_task)) {
376                og_dbi_close(dbi);
377                return -1;
378        }
379        og_dbi_close(dbi);
380
381        return 0;
382}
383
384static int og_resp_refresh(json_t *data, struct og_client *cli)
385{
386        struct og_partition partitions[OG_PARTITION_MAX] = {};
387        struct og_partition disks[OG_DISK_MAX] = {};
388        const char *serial_number = NULL;
389        struct og_computer computer = {};
390        const char *status = NULL;
391        char cfg[4096] = {};
392        struct og_dbi *dbi;
393        uint32_t link = 0;
394        const char *key;
395        unsigned int i;
396        json_t *value;
397        int err = 0;
398        bool res;
399
400        if (json_typeof(data) != JSON_OBJECT)
401                return -1;
402
403        json_object_foreach(data, key, value) {
404                if (!strcmp(key, "disk_setup")) {
405                        err = og_json_parse_partition_array(value, disks);
406                } else if (!strcmp(key, "partition_setup")) {
407                        err = og_json_parse_partition_array(value, partitions);
408                } else if (!strcmp(key, "serial_number")) {
409                        err = og_json_parse_string(value, &serial_number);
410                } else if (!strcmp(key, "status")) {
411                        err = og_json_parse_string(value, &status);
412                } else if (!strcmp(key, "link")) {
413                        err = og_json_parse_uint(value, &link);
414                }
415
416                if (err < 0)
417                        return err;
418        }
419
420        if (link)
421                cli->speed = link;
422
423        if (status) {
424                if (!strncmp(status, "LINUX", strlen("LINUX"))) {
425                        cli->status = OG_CLIENT_STATUS_LINUX;
426                } else if (!strncmp(status, "WIN", strlen("WIN"))) {
427                        cli->status = OG_CLIENT_STATUS_WIN;
428                }
429                return 0;
430        }
431
432        if (strlen(serial_number) > 0)
433                snprintf(cfg, sizeof(cfg), "ser=%s\n", serial_number);
434
435        for (i = 0; i < OG_DISK_MAX; i++) {
436                if (!disks[i].disk || !disks[i].number ||
437                    !disks[i].code || !disks[i].filesystem ||
438                    !disks[i].os || !disks[i].size ||
439                    !disks[i].used_size)
440                        continue;
441
442                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
443                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\tdtype=%s\n",
444                         disks[i].disk, disks[i].number,
445                         disks[i].code, disks[i].filesystem,
446                         disks[i].os, disks[i].size,
447                         disks[i].used_size, disks[i].disk_type);
448        }
449
450        for (i = 0; i < OG_PARTITION_MAX; i++) {
451                if (!partitions[i].disk || !partitions[i].number ||
452                    !partitions[i].code || !partitions[i].filesystem ||
453                    !partitions[i].os || !partitions[i].size ||
454                    !partitions[i].used_size)
455                        continue;
456
457                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
458                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
459                         partitions[i].disk, partitions[i].number,
460                         partitions[i].code, partitions[i].filesystem,
461                         partitions[i].os, partitions[i].size,
462                         partitions[i].used_size);
463        }
464
465        dbi = og_dbi_open(&ogconfig.db);
466        if (!dbi) {
467                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
468                                  __func__, __LINE__);
469                return -1;
470        }
471
472        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
473        if (err < 0) {
474                og_dbi_close(dbi);
475                return -1;
476        }
477
478        res = actualizaConfiguracion(dbi, cfg, computer.id);
479        og_dbi_close(dbi);
480
481        if (!res) {
482                syslog(LOG_ERR, "Problem updating client configuration\n");
483                return -1;
484        }
485
486        if (!cli->autorun && computer.procedure_id) {
487                cli->autorun = true;
488
489                if (og_dbi_queue_autorun(computer.id, computer.procedure_id))
490                        return -1;
491        }
492
493        return 0;
494}
495
496static int update_image_info(struct og_dbi *dbi, const char *image_id,
497                             const char *clonator, const char *compressor,
498                             const char *filesystem, const uint64_t datasize)
499{
500        const char *msglog;
501        dbi_result result;
502
503        result = dbi_conn_queryf(dbi->conn,
504                "UPDATE imagenes"
505                "   SET clonator='%s', compressor='%s',"
506                "       filesystem='%s', datasize=%lld"
507                " WHERE idimagen=%s", clonator, compressor, filesystem,
508                datasize, image_id);
509
510        if (!result) {
511                dbi_conn_error(dbi->conn, &msglog);
512                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
513                       __func__, __LINE__, msglog);
514                return -1;
515        }
516        dbi_result_free(result);
517
518        return 0;
519}
520
521static int og_resp_image_create(json_t *data, struct og_client *cli)
522{
523        struct og_software_legacy soft_legacy;
524        struct og_image_legacy img_legacy;
525        struct og_computer computer = {};
526        const char *compressor = NULL;
527        const char *filesystem = NULL;
528        const char *partition = NULL;
529        const char *software = NULL;
530        const char *image_id = NULL;
531        const char *clonator = NULL;
532        const char *disk = NULL;
533        const char *code = NULL;
534        const char *name = NULL;
535        const char *repo = NULL;
536        uint64_t datasize = 0;
537        struct og_dbi *dbi;
538        const char *key;
539        json_t *value;
540        int err = 0;
541        bool res;
542
543        if (json_typeof(data) != JSON_OBJECT)
544                return -1;
545
546        json_object_foreach(data, key, value) {
547                if (!strcmp(key, "software"))
548                        err = og_json_parse_string(value, &software);
549                else if (!strcmp(key, "partition"))
550                        err = og_json_parse_string(value, &partition);
551                else if (!strcmp(key, "disk"))
552                        err = og_json_parse_string(value, &disk);
553                else if (!strcmp(key, "code"))
554                        err = og_json_parse_string(value, &code);
555                else if (!strcmp(key, "id"))
556                        err = og_json_parse_string(value, &image_id);
557                else if (!strcmp(key, "name"))
558                        err = og_json_parse_string(value, &name);
559                else if (!strcmp(key, "repository"))
560                        err = og_json_parse_string(value, &repo);
561                else if (!strcmp(key, "clonator"))
562                        err = og_json_parse_string(value, &clonator);
563                else if (!strcmp(key, "compressor"))
564                        err = og_json_parse_string(value, &compressor);
565                else if (!strcmp(key, "filesystem"))
566                        err = og_json_parse_string(value, &filesystem);
567                else if (!strcmp(key, "datasize"))
568                        err = og_json_parse_uint64(value, &datasize);
569
570                if (err < 0)
571                        return err;
572        }
573
574        if (!software || !partition || !disk || !code || !image_id || !name ||
575            !repo || !clonator || !compressor || !filesystem || !datasize) {
576                syslog(LOG_ERR, "malformed response json\n");
577                return -1;
578        }
579
580        dbi = og_dbi_open(&ogconfig.db);
581        if (!dbi) {
582                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
583                       __func__, __LINE__);
584                return -1;
585        }
586
587        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
588        if (err < 0) {
589                og_dbi_close(dbi);
590                return -1;
591        }
592
593        snprintf(soft_legacy.center, sizeof(soft_legacy.center), "%d",
594                 computer.center);
595        snprintf(soft_legacy.software, sizeof(soft_legacy.software), "%s",
596                 software);
597        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
598                 image_id);
599        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
600        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
601        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
602        snprintf(img_legacy.code, sizeof(img_legacy.code), "%s", code);
603        snprintf(img_legacy.name, sizeof(img_legacy.name), "%s", name);
604        snprintf(img_legacy.repo, sizeof(img_legacy.repo), "%s", repo);
605
606        res = actualizaSoftware(dbi,
607                                soft_legacy.software,
608                                img_legacy.part,
609                                soft_legacy.id,
610                                computer.name,
611                                soft_legacy.center);
612        if (!res) {
613                og_dbi_close(dbi);
614                syslog(LOG_ERR, "Problem updating client configuration\n");
615                return -1;
616        }
617
618        res = actualizaCreacionImagen(dbi,
619                                      img_legacy.image_id,
620                                      img_legacy.disk,
621                                      img_legacy.part,
622                                      img_legacy.code,
623                                      img_legacy.repo,
624                                      soft_legacy.id);
625        if (!res) {
626                og_dbi_close(dbi);
627                syslog(LOG_ERR, "Problem updating client configuration\n");
628                return -1;
629        }
630
631        res = update_image_info(dbi, image_id, clonator, compressor,
632                                filesystem, datasize);
633        og_dbi_close(dbi);
634
635        if (res) {
636                syslog(LOG_ERR, "Problem updating image info\n");
637                return -1;
638        }
639
640        return 0;
641}
642
643static int og_resp_image_restore(json_t *data, struct og_client *cli)
644{
645        struct og_software_legacy soft_legacy;
646        struct og_image_legacy img_legacy;
647        struct og_computer computer = {};
648        const char *partition = NULL;
649        const char *image_id = NULL;
650        const char *disk = NULL;
651        const char *msglog;
652        struct og_dbi *dbi;
653        dbi_result result;
654        const char *key;
655        json_t *value;
656        int err = 0;
657
658        if (json_typeof(data) != JSON_OBJECT)
659                return -1;
660
661        json_object_foreach(data, key, value) {
662                if (!strcmp(key, "partition"))
663                        err = og_json_parse_string(value, &partition);
664                else if (!strcmp(key, "disk"))
665                        err = og_json_parse_string(value, &disk);
666                else if (!strcmp(key, "image_id"))
667                        err = og_json_parse_string(value, &image_id);
668
669                if (err < 0)
670                        return err;
671        }
672
673        if (!partition || !disk || !image_id) {
674                syslog(LOG_ERR, "malformed response json\n");
675                return -1;
676        }
677
678        dbi = og_dbi_open(&ogconfig.db);
679        if (!dbi) {
680                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
681                       __func__, __LINE__);
682                return -1;
683        }
684
685        result = dbi_conn_queryf(dbi->conn,
686                                 "SELECT idperfilsoft FROM imagenes "
687                                 " WHERE idimagen='%s'", image_id);
688        if (!result) {
689                og_dbi_close(dbi);
690                syslog(LOG_ERR, "failed to query database\n");
691                return -1;
692        }
693        if (!dbi_result_next_row(result)) {
694                dbi_result_free(result);
695                og_dbi_close(dbi);
696                syslog(LOG_ERR, "software profile does not exist in database\n");
697                return -1;
698        }
699        snprintf(img_legacy.software_id, sizeof(img_legacy.software_id),
700                 "%d", dbi_result_get_uint(result, "idperfilsoft"));
701        dbi_result_free(result);
702
703        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
704        if (err < 0) {
705                og_dbi_close(dbi);
706                return -1;
707        }
708
709        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
710                 image_id);
711        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
712        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
713        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
714
715        result = dbi_conn_queryf(dbi->conn,
716                                 "UPDATE ordenadores_particiones"
717                                 "   SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW(),"
718                                 "       revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
719                                 "       idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)"
720                                 " WHERE idordenador=%s AND numdisk=%s AND numpar=%s",
721                                 img_legacy.image_id, img_legacy.software_id,
722                                 img_legacy.image_id, img_legacy.software_id,
723                                 soft_legacy.id, img_legacy.disk, img_legacy.part);
724        if (!result) {
725                dbi_conn_error(dbi->conn, &msglog);
726                syslog(LOG_ERR, "failed to update database (%s:%d) %s\n",
727                       __func__, __LINE__, msglog);
728                og_dbi_close(dbi);
729                return -1;
730        }
731        dbi_result_free(result);
732        og_dbi_close(dbi);
733
734        return 0;
735}
736
737static int og_agent_http_response_code(const char *buf)
738{
739        if (!strncmp(buf, "HTTP/1.0 200 OK", strlen("HTTP/1.0 200 OK"))) {
740                return 200;
741        } else if (!strncmp(buf, "HTTP/1.0 202 Accepted",
742                            strlen("HTTP/1.0 202 Accepted"))) {
743                return 202;
744        } else if (!strncmp(buf, "HTTP/1.0 400 Bad Request",
745                            strlen("HTTP/1.0 400 Bad Request"))) {
746                return 400;
747        } else if (!strncmp(buf, "HTTP/1.0 500 Internal Server Error",
748                            strlen("HTTP/1.0 500 Internal Server Error"))) {
749                return 500;
750        } else if (!strncmp(buf, "HTTP/1.0 503 Service Unavailable",
751                            strlen("HTTP/1.0 503 Service Unavailable"))) {
752                return 503;
753        } else if (!strncmp(buf, "HTTP/1.0 103 Early Hints",
754                            strlen("HTTP/1.0 103 Early Hints"))) {
755                return 103;
756        }
757
758        return -1;
759}
760
761int og_agent_state_process_response(struct og_client *cli)
762{
763        int ret, err = -1, code;
764        json_error_t json_err;
765        bool success;
766        json_t *root;
767        char *body;
768
769        code = og_agent_http_response_code(cli->buf);
770        switch (code) {
771        case 103:
772        case 200:
773                ret = 0;
774                success = true;
775                break;
776        case 202:
777                ret = 1;
778                success = true;
779                break;
780        case 400:
781                ret = -1;
782                success = false;
783                syslog(LOG_ERR, "Client %s:%hu reports malformed HTTP request from server\n",
784                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
785                break;
786        case 500:
787                ret = 0;
788                success = false;
789                cli->last_cmd = OG_CMD_UNSPEC;
790                syslog(LOG_ERR, "Client %s:%hu reports failure to process command\n",
791                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
792                /* ... cancel pending actions related to this task for this client here */
793                break;
794        case 503:
795                ret = 1;
796                success = false;
797                syslog(LOG_ERR, "Client %s:%hu is busy to process command\n",
798                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
799                break;
800        default:
801                ret = -1;
802                success = false;
803                syslog(LOG_ERR, "Client %s:%hu reports unknown HTTP response code\n",
804                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
805                break;
806        }
807
808        if (success)
809                cli->last_cmd_result = OG_SUCCESS;
810        else
811                cli->last_cmd_result = OG_FAILURE;
812
813        if (code != 200 && code != 103) {
814                og_dbi_update_action(cli->last_cmd_id, success);
815                cli->last_cmd_id = 0;
816                return ret;
817        }
818
819        if (!cli->content_length) {
820                og_dbi_update_action(cli->last_cmd_id, true);
821                cli->last_cmd_id = 0;
822                cli->last_cmd = OG_CMD_UNSPEC;
823                return 0;
824        }
825
826        body = strstr(cli->buf, "\r\n\r\n") + 4;
827
828        root = json_loads(body, 0, &json_err);
829        if (!root) {
830                syslog(LOG_ERR, "%s:%d: malformed json line %d: %s\n",
831                       __FILE__, __LINE__, json_err.line, json_err.text);
832                return -1;
833        }
834
835        if (code == 103) {
836                err = og_resp_early_hints(cli, root);
837                json_decref(root);
838                return err;
839        }
840
841        switch (cli->last_cmd) {
842        case OG_CMD_PROBE:
843                err = og_resp_probe(cli, root);
844                break;
845        case OG_CMD_SHELL_RUN:
846                err = og_resp_shell_run(cli, root);
847                break;
848        case OG_CMD_HARDWARE:
849                err = og_resp_hardware(root, cli);
850                break;
851        case OG_CMD_SOFTWARE:
852                err = og_resp_software(root, cli);
853                break;
854        case OG_CMD_REFRESH:
855                err = og_resp_refresh(root, cli);
856                break;
857        case OG_CMD_SETUP:
858                err = og_resp_refresh(root, cli);
859                break;
860        case OG_CMD_IMAGE_CREATE:
861                err = og_resp_image_create(root, cli);
862                break;
863        case OG_CMD_IMAGE_RESTORE:
864                err = og_resp_image_restore(root, cli);
865                break;
866        default:
867                err = -1;
868                break;
869        }
870
871        json_decref(root);
872
873        if (err < 0) {
874                err = 0;
875                success = false;
876                cli->last_cmd_result = OG_FAILURE;
877                /* ... cancel pending actions related to this task for this client here */
878        }
879
880        og_dbi_update_action(cli->last_cmd_id, success);
881        cli->last_cmd_id = 0;
882        cli->last_cmd = OG_CMD_UNSPEC;
883
884        return err;
885}
Note: See TracBrowser for help on using the repository browser.