source: ogServer-Git/src/client.c @ c0573b9

Last change on this file since c0573b9 was 9b61713, checked in by Javier Sánchez Parra <jsanchez@…>, 3 years ago

#915 Fix conditional jump depending on uninitialised value

Valgrind says:

==9452== 1 errors in context 1 of 38:
==9452== Conditional jump or move depends on uninitialised value(s)
==9452== at 0x11BD1E: og_resp_refresh (client.c:383)
==9452== by 0x11CF2A: og_agent_state_process_response (client.c:822)
==9452== by 0x112FCE: og_agent_read_cb (core.c:254)
==9452== by 0x4E41D72: ev_invoke_pending (in /usr/lib/x86_64-linux-gnu/libev.so.4.0.0)
==9452== by 0x4E453DD: ev_run (in /usr/lib/x86_64-linux-gnu/libev.so.4.0.0)
==9452== by 0x1107CD: ev_loop (ev.h:835)
==9452== by 0x1107CD: main (main.c:108)
==9452== Uninitialised value was created by a stack allocation
==9452== at 0x11BB02: og_resp_refresh (client.c:348)

Fixes: f03425e ("#915 Add support for link speed in the refresh response")

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