From patchwork Thu Oct 28 09:15:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Babic X-Patchwork-Id: 1547377 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.a=rsa-sha256 header.s=20210112 header.b=N5tq/K4a; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=googlegroups.com (client-ip=2a00:1450:4864:20::138; helo=mail-lf1-x138.google.com; envelope-from=swupdate+bncbcxploxj6ikrblou5gfqmgqetqbawia@googlegroups.com; receiver=) Received: from mail-lf1-x138.google.com (mail-lf1-x138.google.com [IPv6:2a00:1450:4864:20::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Hg0Jz20drz9sRN for ; Thu, 28 Oct 2021 20:15:30 +1100 (AEDT) Received: by mail-lf1-x138.google.com with SMTP id z1-20020a056512308100b003ff78e6402bsf2601629lfd.4 for ; Thu, 28 Oct 2021 02:15:29 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1635412525; cv=pass; d=google.com; s=arc-20160816; b=ssKJktbWHkf5q2T5gND9aXpSgk8PqJjhKGDldfxqx/qecuOiAX71lBpRhf4OJ6D7go wM9c75OJxhFTmpvOpaMX/+cAfxaczlGhD+Bo1yFrrd/1E7IkE/QHZuAbOkqyse1Pyfb+ d5Oteo6r7Te3e0Dsy+JAe10rqmey+gD8tNZyg1exz++34aVpqIQk1YB1vuVDgEpLPCOm UXaYRNrOAdIcLWP9B6ejqqzuIfSRAqzVPenQIJ4jqdyvILJ9qZBaQR/EyA828hbYV7rg eBPKJocW7weulQweS2duq+4CH7Wzsz+HE8NiQ5oG/a490u99r8hvksizw3RVhZqaONDJ Np1w== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:dkim-signature; bh=Dd1OGePuwkUzWKq8CijJKRM7gV+8cownNQcS+HihZhk=; b=olzj+takJhQFWTEiDTjuXBssjBuLW19JC8xfjiFZPC1TfTum5sWt5e6+JNUrhiVAZI 2uf7OlxU339HE7Fkn5ClK50V7ACGX2nkyHShaioPbdWS7dOa6m48iUbacPekPCapxtvb 3AVqEBY8Ix7loAAboQpWeO1do5pGq9zcFA5Um2ZELSRaSksJfAe0F+FTnuW5JjuAFeHp VW6D8BdQxLOpPU5hEPFbscceDZ47S9RQuq9+rz7sXinYn9ZCO+UL9n9PLNxzz3PIYdWw TBaewKPS1koNKMUHG3AgxSGW2sIHVQNnD6qFyvhL7YTdRsNAgWTT2dPNBD1HLhwlYhT/ W/+A== ARC-Authentication-Results: i=2; gmr-mx.google.com; spf=neutral (google.com: 212.18.0.9 is neither permitted nor denied by domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20210112; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=Dd1OGePuwkUzWKq8CijJKRM7gV+8cownNQcS+HihZhk=; b=N5tq/K4aZfC0b7I/bJ1hjyHfUsETXhfcZE/A5Lj+Hpo7vCb7azbsWDPDHJd6lnV96R +9gb3nqRcDCMks38UdS5xtq2GGdlNYMZGkVE1Ji+LY0QGE7uULtnYO2LHcOZZDiAjl5x nnsz6WQXbkkfBamt8YMmAEikr+iwcpG82LdnKMiTkD/oGEWrIeTvtSZ+/KfhC7rRFSZV LQM1qZJqoQrCakILTui/cocTUcOuwvEF871bSJSmyRf8G513XpaJ6IW3zCnN6R+zUnre AQ11rvH1bIQcDm8dYx6w2XBna/faCOr0WCBX+v6VDwsH/A7WecvfNcsvghstKvdPfo0B nJ6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=sender:x-gm-message-state:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-spam-checked-in-group:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=Dd1OGePuwkUzWKq8CijJKRM7gV+8cownNQcS+HihZhk=; b=qPra/YVT5PhGi8guzP51ZYIAmjUNC0wo0DcOO88xudEtggd1HQf56IPeHncOgHLfxP N2Ch1GhOdWl3WypXHIIVBdLlmAH2q88juPmgG2Q9q1CaER9Y6YOb19tdQn8BoJpuGram oGQQHDt6ovzKMDRuQXcrr7N+YLDq1tu9ycAitXSAizc6op8DxGd9TD1Z+VcOhXkoFKEo zT/48BvsIDWZ6I+TSF92Pj3f9fWa+saUrXKxS96x1EENRd4A9DLvJx+CrMv+Ou17Zk5r DnFOlpakGmR6RfiW62ZPhn5fiuqFfXFsAMAySOBShRpKPVjX2+vluLRQKYY3qDu1UwBi daEg== Sender: swupdate@googlegroups.com X-Gm-Message-State: AOAM5326ILQ0YgcBAHWNg4vpWToq2ST16EHgv5VyuCaXSJL2+ODd0+cH kirvDDWXgx24QCIMwY/DbF8= X-Google-Smtp-Source: ABdhPJw222G0u257fMRUyPmCh+ZJtLT17NVz+9IvelgagKUPFI9h6pv9rH99nlohLfSCwSuudl4PdA== X-Received: by 2002:a05:6512:344b:: with SMTP id j11mr2963484lfr.379.1635412525602; Thu, 28 Oct 2021 02:15:25 -0700 (PDT) X-BeenThere: swupdate@googlegroups.com Received: by 2002:a05:651c:a0f:: with SMTP id k15ls493407ljq.5.gmail; Thu, 28 Oct 2021 02:15:24 -0700 (PDT) X-Received: by 2002:a2e:8843:: with SMTP id z3mr3381885ljj.257.1635412524560; Thu, 28 Oct 2021 02:15:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1635412524; cv=none; d=google.com; s=arc-20160816; b=0TBAxRXPbm/hyP/6NY2NpBieZZdtTDquAGQWEIQ10KPyZChYKtxACf6gx4BEtuYBy1 ++xgA6HJzSHDgn9ft7mgL3+hs6Zvgqe4UA620iF9oPL1/XDC/acsGlIqd3bfUCfmNSnC xWz2kTKz47n0ptzGaUn9+6HylKCEx2iRwP+ZtsTYHKcORjMahBtmadtOICbhNolJKtMV 3339x8v6jjJR0ad5qTQkvve0DmBUQsO7aIR3Uxn8OyXOZ8cmTva2LmKm1sp6k2ecS86R GvXtnxAzzi+S1Fgs/2PcwNS+GBrKAEjZ0/jit3pl2hgfsAiTiBg/yFUOuFA3SSP0jblD 5pew== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from; bh=9KV9p6VtRIB/26o0FWs+aEDN2TJa+Ewtqm0OcGs+hMs=; b=B8LoYbGg08lz+Whn57tEj7EHNwmazde8DA5xxyKu8fCTcuYt3RE+Pmd4Z0I9Sf2+nj Kqewhy9VTYoS85dT28nPP85aznBhzQ/GZmxxfmyqkznJli2WbbA5hltxg2q3vahexqDJ qgwi0Rrws8FhsXtJV+41EgjM1Pe6K8Nh4cWTfyzdjtC2r/BzNQ9lLXckYc0BvBNVIkkf bbfjBb8RXprBQzUHEM5N67ZJKbR8l4aSjld+8IM6z9kdOvtREyCXjKl6j0tP67LnT+mx dS0XxNTPU6+eVWgXNTmqDWxBmEDZZ8+nUXlFIa77PnKmcc0aa8HOmsqmR3mX7NFJD0av ZucA== ARC-Authentication-Results: i=1; gmr-mx.google.com; spf=neutral (google.com: 212.18.0.9 is neither permitted nor denied by domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de Received: from mail-out.m-online.net (mail-out.m-online.net. [212.18.0.9]) by gmr-mx.google.com with ESMTPS id v2si29338lfo.2.2021.10.28.02.15.24 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 28 Oct 2021 02:15:24 -0700 (PDT) Received-SPF: neutral (google.com: 212.18.0.9 is neither permitted nor denied by domain of sbabic@denx.de) client-ip=212.18.0.9; Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 4Hg0Jq6kMtz1qwGf; Thu, 28 Oct 2021 11:15:23 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 4Hg0Jq6Q33z1qqkB; Thu, 28 Oct 2021 11:15:23 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id jMshEmNWsSWN; Thu, 28 Oct 2021 11:15:22 +0200 (CEST) Received: from babic.homelinux.org (host-88-217-136-221.customer.m-online.net [88.217.136.221]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPS; Thu, 28 Oct 2021 11:15:22 +0200 (CEST) Received: from localhost (mail.babic.homelinux.org [127.0.0.1]) by babic.homelinux.org (Postfix) with ESMTP id 95D0C45406CB; Thu, 28 Oct 2021 11:15:21 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at babic.homelinux.org Received: from babic.homelinux.org ([127.0.0.1]) by localhost (mail.babic.homelinux.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id p9qgtklxR2vj; Thu, 28 Oct 2021 11:15:17 +0200 (CEST) Received: from paperino.fritz.box (paperino.fritz.box [192.168.178.48]) by babic.homelinux.org (Postfix) with ESMTP id 104294540BCF; Thu, 28 Oct 2021 11:15:17 +0200 (CEST) From: Stefano Babic To: swupdate@googlegroups.com Cc: Stefano Babic Subject: [swupdate] [PATCH 1/3] swupdate-ipc: just one tool for IPC Date: Thu, 28 Oct 2021 11:15:11 +0200 Message-Id: <20211028091513.2875447-2-sbabic@denx.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211028091513.2875447-1-sbabic@denx.de> References: <20211028091513.2875447-1-sbabic@denx.de> MIME-Version: 1.0 X-Original-Sender: sbabic@denx.de X-Original-Authentication-Results: gmr-mx.google.com; spf=neutral (google.com: 212.18.0.9 is neither permitted nor denied by domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de Precedence: list Mailing-list: list swupdate@googlegroups.com; contact swupdate+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: swupdate@googlegroups.com X-Google-Group-Id: 605343134186 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , This contains and replace most of the tools, including swupdate-gethawkbitstatus swupdate-hawkbitcfg swupdate-sendtohawkbit swupdate-sysrestart The syntax for a single command is compatible with the past. Just run: swupdate-ipc Signed-off-by: Stefano Babic --- tools/Makefile | 3 +- tools/swupdate-ipc.c | 616 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 618 insertions(+), 1 deletion(-) create mode 100644 tools/swupdate-ipc.c diff --git a/tools/Makefile b/tools/Makefile index 8c495c94..5e43f91d 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -14,7 +14,8 @@ lib-y += \ swupdate-progress.o \ swupdate-hawkbitcfg.o \ swupdate-sendtohawkbit.o \ - swupdate-sysrestart.o + swupdate-sysrestart.o \ + swupdate-ipc.o # # Uncomment the next lines to integrate the compiling/linking of # # any .c files placed alongside the above "official" tools in the diff --git a/tools/swupdate-ipc.c b/tools/swupdate-ipc.c new file mode 100644 index 00000000..efa58018 --- /dev/null +++ b/tools/swupdate-ipc.c @@ -0,0 +1,616 @@ +/* + * (C) Copyright 2021 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +/* + * This is a simple example how to send a command to + * a SWUpdate's subprocess. It sends a "feedback" + * to the suricatta module and waits for the answer. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "network_ipc.h" +#include + +struct cmd_t; +typedef void (*help)(const char *name); +typedef int (*cmdfunc)(struct cmd_t *cmd, int argc, char *argv[]); + +typedef struct cmd_t { + const char *name; + cmdfunc fn; + help usage; +} cmd_t; + +static void usage_aes(const char *program) { + fprintf(stdout, "\t %s \n", program); +} + +static void usage_gethawkbitstatus(const char *program) { + fprintf(stdout, "\t %s\n", program); +} + +static void usage_setversion(const char *program) { + fprintf(stdout, "\t %s \n", program); +} + +static void usage_send_to_hawkbit(const char *program) { + fprintf(stdout, "\t %s " + " ..\n", program); +} + +static void usage_sysrestart(const char *programname) +{ + fprintf(stdout, "\t %s [OPTION]\n", programname); + fprintf(stdout, + "\t\t-w, --wait : wait for a connection with SWUpdate\n" + "\t\t-s, --socket : path to progress IPC socket\n" + "\t\t-h, --help : print this help and exit\n" + ); +} + +static void usage_hawkbitcfg(const char *program) { + fprintf(stdout,"\t %s \n", program); + fprintf(stdout, + "\t\t-p, --polling-time : Set polling time (0=from server) to ask the backend server\n" + "\t\t-e, --enable : Enable polling of backend server\n" + "\t\t-d, --disable : Disable polling of backend server\n" + ); +} + +static bool check_ascii_char(const char *s) { + int i; + + if (!s) + return false; + for (i = 0; i < strlen(s); i++) { + if ((s[i] >= '0' && s[i] <= '9') || + (s[i] >= 'A' && s[i] <= 'F')) + continue; + return false; + } + + return true; +} + +static void send_msg(ipc_message *msg) +{ + int rc; + + fprintf(stdout, "Sending: '%s'", msg->data.procmsg.buf); + rc = ipc_send_cmd(msg); + + fprintf(stdout, " returned %d\n", rc); + if (rc == 0) { + fprintf(stdout, "Server returns %s\n", + (msg->type == ACK) ? "ACK" : "NACK"); + if (msg->data.procmsg.len > 0) { + fprintf(stdout, "Returned message: %s\n", + msg->data.procmsg.buf); + } + } +} + +/* + * Implementation of single commands + */ + +static struct option hawkbitcfg_options[] = { + {"help", no_argument, NULL, 'h'}, + {"polling-time", required_argument, NULL, 'p'}, + {"enable", no_argument, NULL, 'e'}, + {"disable", no_argument, NULL, 'd'}, + {NULL, 0, NULL, 0} +}; + +static int hawkbitcfg(cmd_t __attribute__((__unused__)) *cmd, int argc, char *argv[]) { + ipc_message msg; + size_t size; + char *buf; + int c; + unsigned long polling_time; + bool enable = false; + int opt_e = 0; + int opt_p = 0; + + memset(&msg, 0, sizeof(msg)); + msg.data.procmsg.source = SOURCE_SURICATTA; + msg.type = SWUPDATE_SUBPROCESS; + + size = sizeof(msg.data.procmsg.buf); + buf = msg.data.procmsg.buf; + + /* Process options with getopt */ + while ((c = getopt_long(argc, argv, "p:edh", + hawkbitcfg_options, NULL)) != EOF) { + switch (c) { + case 'p': + opt_p = 1; + msg.data.procmsg.cmd = CMD_CONFIG; + polling_time = strtoul(optarg, NULL, 10); + break; + case 'e': + case 'd': + msg.data.procmsg.cmd = CMD_ENABLE; + opt_e = 1; + enable = (c == 'e'); + break; + } + } + + /* + * Build a json string with the command line parameters + * do not check anything, let SWUpdate + * doing the checks + * An error or a NACK is returned in + * case of failure + */ + if (opt_p) { + snprintf(buf, size, "{ \"polling\" : \"%lu\"}", polling_time); + msg.data.procmsg.len = strnlen(buf, size); + send_msg(&msg); + } + if (opt_e) { + snprintf(buf, size, "{ \"enable\" : %s}", enable ? "true" : "false"); + msg.data.procmsg.len = strnlen(buf, size); + send_msg(&msg); + } + + exit(0); +} + +static int sendtohawkbit(cmd_t *cmd, int argc, char *argv[]) { + int written, i; + ipc_message msg; + size_t size; + char *buf; + + if (argc < 3) { + cmd->usage(argv[0]); + return 1; + } + + memset(&msg, 0, sizeof(msg)); + msg.data.procmsg.source = SOURCE_SURICATTA; + msg.data.procmsg.cmd = CMD_ACTIVATION; + msg.type = SWUPDATE_SUBPROCESS; + + size = sizeof(msg.data.procmsg.buf); + buf = msg.data.procmsg.buf; + + /* + * Build a json string with the command line parameters + * do not check anything, let SWUpdate + * doing the checks + * An error or a NACK is returned in + * case of failure + */ + for (i = 1; i < argc; i++) { + switch (i) { + case 1: + written = snprintf(buf, size, "{ \"id\" : \"%lu\"", strtoul(argv[i], NULL, 10)); + break; + case 2: + written = snprintf(buf, size, ", \"status\" : \"%s\"", argv[i]); + break; + case 3: + written = snprintf(buf, size, ",\"finished\" : \"%s\"", argv[i]); + break; + case 4: + written = snprintf(buf, size, ",\"execution\" : \"%s\"", argv[i]); + break; + case 5: + written = snprintf(buf, size, ",\"details\" : [ \"%s\"", argv[i]); + break; + default: + written = snprintf(buf, size, ",\"%s\"", argv[i]); + break; + } + + buf += written; + size -= written; + + if (size <= 0) + break; + } + + if (i > 5) + written = snprintf(buf, size, "]}"); + else + written = snprintf(buf, size, "}"); + + fprintf(stdout, "Sending: '%s'", msg.data.procmsg.buf); + msg.data.procmsg.len = strnlen(msg.data.procmsg.buf, sizeof(msg.data.procmsg.buf)); + + send_msg(&msg); + + return 0; +} + +#if defined(CONFIG_JSON) +#include +static int gethawkbitstatus(cmd_t __attribute__((__unused__)) *cmd, + int __attribute__((__unused__)) argc, + char __attribute__((__unused__)) *argv[]) { + ipc_message msg; + struct json_object *parsed_json; + struct json_object *server; + struct json_object *status; + struct json_object *time; + + msg.type = SWUPDATE_SUBPROCESS; + msg.data.procmsg.source = SOURCE_SURICATTA; + msg.data.procmsg.cmd = CMD_GET_STATUS; + + msg.data.procmsg.buf[0] = '\0'; + msg.data.procmsg.len = 0; + msg.data.procmsg.timeout = 10; /* Wait 10 s for Suricatta response */ + + send_msg(&msg); + + if (msg.type == ACK) { + parsed_json = json_tokener_parse(msg.data.procmsg.buf); + json_object_object_get_ex(parsed_json, "server", &server); + json_object_object_get_ex(server, "status", &status); + json_object_object_get_ex(server, "time", &time); + + fprintf(stdout, "status: %d, time: %s\n", + json_object_get_int(status), + json_object_get_string(time)); + return 0; + } else { + fprintf(stderr, "Error: suricatta did respond with NACK.\n"); + return 1; + } + +} + +#else +static int gethawkbitstatus(cmd_t *cmd, int __attribute__((__unused__)) argc, char **argv) { + fprintf(stderr, "%s: JSON not available, exiting..\n", argv[1]); + return 1; +} +#endif + +static int sendaes(cmd_t *cmd, int argc, char *argv[]) { + char *key, *ivt; + if (argc != 3) { + cmd->usage(argv[0]); + return 1; + } + key = argv[1]; + ivt = argv[2]; + if (strlen(key) != 64 || strlen(ivt) != 32) { + fprintf(stderr, "Wrong format for AES /IVT\n"); + cmd->usage(argv[0]); + return 1; + } + if (!check_ascii_char(key) || !check_ascii_char(ivt)) { + fprintf(stderr, "Wrong chars in keys\n"); + return 1; + } + if (swupdate_set_aes(key, ivt)) { + fprintf(stderr, "Error setting AES KEY\n"); + return 1; + } + + return 0; +} + +static int setversions(cmd_t *cmd, int argc, char *argv[]) { + if (argc != 4) { + cmd->usage(argv[0]); + return 1; + } + + if (swupdate_set_version_range(argv[2], argv[3], argv[4])) { + fprintf(stderr, "Error IPC setting versions\n"); + return 1; + } + return 0; +} + +#if defined(CONFIG_CURL) +#include + +#define MAX_DEVS 100 +#define PATTERN "REMOTE:" + + +/* Store the ip addresses of device to be rebooted */ +static char ipaddrs[MAX_DEVS][NI_MAXHOST]; + +static bool is_ipaddress(char *ipaddr) +{ + struct sockaddr_in sa; + int result = inet_pton(AF_INET, ipaddr, &(sa.sin_addr)); + return result == 1; +} + +static struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + {"wait", no_argument, NULL, 'w'}, + {"socket", required_argument, NULL, 's'}, + {NULL, 0, NULL, 0} +}; + +static void usage(char *programname) +{ + fprintf(stdout, "%s (compiled %s)\n", programname, __DATE__); + fprintf(stdout, "Usage %s [OPTION]\n", + programname); + fprintf(stdout, + " -w, --wait : wait for a connection with SWUpdate\n" + " -s, --socket : path to progress IPC socket\n" + " -h, --help : print this help and exit\n" + ); +} + +static void restart_system(unsigned int ndevs) +{ + int dev; + CURL *curl_handle; /* CURL handle */ + char url[NI_MAXHOST + 20]; + CURLcode curlrc; + struct ifaddrs *ifaddr, *ifa; + char local[NI_MAXHOST]; + + /* + * Drop local ip address from the list to avoid that + * this board reboots before sending all messages + * A local reboot will be done by calling reboot() + */ + if (getifaddrs(&ifaddr) != -1) { + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if ((ifa->ifa_addr == NULL) || (ifa->ifa_addr->sa_family != AF_INET)) + continue; + if (getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), + local, NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) + continue; + + for (dev = 0; dev < ndevs; dev++) { + if (!strcmp(local, ipaddrs[dev])) { + printf("LOCAL IP : %s %s\n", local, ipaddrs[dev]); + ipaddrs[dev][0] = '\0'; + } + } + } + } + + freeifaddrs(ifaddr); + + for (dev = 0; dev < ndevs; dev++) { + if (!strlen(ipaddrs[dev])) + continue; + + curl_handle = curl_easy_init(); + /* something very bad, it should never happen */ + if (!curl_handle) + exit(2); + snprintf(url, sizeof(url), "http://%s:8080/restart", ipaddrs[dev]); + if ((curl_easy_setopt(curl_handle, CURLOPT_POST, 1L) != CURLE_OK) || + /* get verbose debug output please */ + (curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, + 1L) != CURLE_OK) || + (curl_easy_setopt(curl_handle, CURLOPT_URL, + url) != CURLE_OK) || + (curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, + "swupdate=reboot") != CURLE_OK) || + (curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, + "libcurl-agent/1.0") != CURLE_OK)) { + fprintf(stderr, "Error setting curl options\n"); + exit(2); + } + + fprintf(stdout, "Rebooting %s\n", url); + + curlrc = curl_easy_perform(curl_handle); + if (curlrc != CURLE_OK && curlrc != CURLE_GOT_NOTHING) { + fprintf(stderr, "Cannot reboot %s, try the next one, error(%d) : %s\n", + ipaddrs[dev], curlrc, curl_easy_strerror(curlrc)); + } + curl_easy_cleanup(curl_handle); + } +} + +static int sysrestart(cmd_t __attribute__((__unused__)) *cmd, int argc, char *argv[]) { + int connfd; + struct progress_msg msg; + int opt_w = 0; + int c; + int ret; + int ndevs = 0; + + RECOVERY_STATUS status = IDLE; /* Update Status (Running, Failure) */ + + /* Process options with getopt */ + while ((c = getopt_long(argc, argv, "whs:", + long_options, NULL)) != EOF) { + switch (c) { + case 'w': + opt_w = 1; + break; + case 's': + SOCKET_PROGRESS_PATH = strdup(optarg); + break; + case 'h': + usage(argv[0]); + exit(0); + break; + default: + usage(argv[0]); + exit(1); + break; + } + } + + /* initialize CURL */ + ret = curl_global_init(CURL_GLOBAL_DEFAULT); + if (ret != CURLE_OK) { + fprintf(stderr, "CURL cannot be initialized, exiting..\n"); + exit(1); + } + + connfd = -1; + while (1) { + if (connfd < 0) { + connfd = progress_ipc_connect(opt_w); + } + + /* + * if still fails, try later + */ + if (connfd < 0) { + sleep(1); + continue; + } + + if (progress_ipc_receive(&connfd, &msg) <= 0) { + continue; + } + + /* + * Something happens, show the info + */ + if ((status == IDLE) && (msg.status != IDLE)) { + fprintf(stdout, "\nUpdate started !\n"); + fprintf(stdout, "Interface: "); + switch (msg.source) { + case SOURCE_UNKNOWN: + fprintf(stdout, "UNKNOWN\n\n"); + break; + case SOURCE_WEBSERVER: + fprintf(stdout, "WEBSERVER\n\n"); + break; + case SOURCE_SURICATTA: + fprintf(stdout, "BACKEND\n\n"); + break; + case SOURCE_DOWNLOADER: + fprintf(stdout, "DOWNLOADER\n\n"); + break; + case SOURCE_LOCAL: + fprintf(stdout, "LOCAL\n\n"); + break; + } + + } + + if (msg.infolen > 0) { + /* + * check that msg is NULL terminated + */ + if (msg.infolen > sizeof(msg.info) - 1) { + msg.infolen = sizeof(msg.info) - 1; + } + msg.info[msg.infolen] = '\0'; + char *ipaddr = strstr(msg.info, PATTERN); + char *end; + if (ipaddr && (strlen(ipaddr) > strlen(PATTERN))) { + ipaddr += strlen(PATTERN); + end = strchr(ipaddr, '}'); + if (end) + *end = '\0'; + if (is_ipaddress(ipaddr)) { + memset(ipaddrs[ndevs], 0, NI_MAXHOST); + strncpy(ipaddrs[ndevs], ipaddr, sizeof(ipaddrs[ndevs])); + fprintf(stdout, "Remote device:%s\n", ipaddr); + ndevs++; + } + } else + fprintf(stdout, "INFO : %s\n", msg.info); + } + + switch (msg.status) { + case SUCCESS: + fprintf(stdout, "Ready to reboot !\n"); + restart_system(ndevs); + sleep(5); + + if (system("reboot") < 0) { /* It should never happen */ + fprintf(stdout, "Please reset the board.\n"); + } + break; + case FAILURE: + ndevs = 0; + break; + case DONE: + fprintf(stdout, "\nDONE.\n"); + break; + default: + break; + } + + status = msg.status; + } + +} +#else + +static int sysrestart(cmd_t *cmd, int __attribute__((__unused__)) argc, char **argv) { + fprintf(stderr, "%s: Curl not available, exiting..\n", argv[1]); + return 1; +} +#endif + +cmd_t commands[] = { + {"aes", sendaes, usage_aes}, + {"setversion",setversions, usage_setversion}, + {"sendtohawkbit", sendtohawkbit, usage_send_to_hawkbit}, + {"hawkbitcfg", hawkbitcfg, usage_hawkbitcfg}, + {"gethawkbit", gethawkbitstatus, usage_gethawkbitstatus}, + {"sysrestart", sysrestart, usage_sysrestart}, + {NULL, NULL} +}; + +static void main_usage(char *program) { + cmd_t *cmd; + + fprintf(stdout, "%s COMMAND [OPTIONS]\n", program); + for (cmd = commands; cmd->name != NULL; cmd ++) { + cmd->usage(cmd->name); + } + + exit(0); +} + +/* + * Simple example, it does nothing but calling the library + */ +int main(int argc, char *argv[]) { + cmd_t *cmd; + if (argc < 2) + main_usage(argv[0]); + + for (cmd = commands; cmd->name != NULL; cmd ++) { + if (!strcmp(cmd->name, argv[1])) { + return cmd->fn(cmd, argc - 1, &argv[1]); + } + } + main_usage(argv[0]); + + exit(1); +} From patchwork Thu Oct 28 09:15:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Babic X-Patchwork-Id: 1547380 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.a=rsa-sha256 header.s=20210112 header.b=gjrwxOWm; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=googlegroups.com (client-ip=2a00:1450:4864:20::23b; helo=mail-lj1-x23b.google.com; envelope-from=swupdate+bncbcxploxj6ikrbmgu5gfqmgqebzhms5y@googlegroups.com; receiver=) Received: from mail-lj1-x23b.google.com (mail-lj1-x23b.google.com [IPv6:2a00:1450:4864:20::23b]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Hg0K04nFXz9sRN for ; Thu, 28 Oct 2021 20:15:32 +1100 (AEDT) Received: by mail-lj1-x23b.google.com with SMTP id f17-20020a2e9751000000b00211a1367c68sf1390576ljj.16 for ; Thu, 28 Oct 2021 02:15:32 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1635412529; cv=pass; d=google.com; s=arc-20160816; b=qoxzmhzUjnerTGq5S6f8QQt8aaP49VPnzwuUAOzZOXdO5okwEoLQHnUerhGCfwlKwB yVKo/YR2g/mAQBGcOUdPtxvupphTaUmAAtWlcwnYb6T6Ve6g8uAd06kAyA7gJmcBpkCu Trk8ndQzML+TSal7/QvqbXX0Qst7YFFrvqnt8Db1d3ZIbxKh0WbkCvbyn9hrx8GoDSjs kZXdYdPB9PapH4mRyYJmk+LN8fnwNJcjx59Lxt7GlaVXDvgD2nZDV+wmuyUNrt6XrVSt io+BHUwxZv9oZOfPn3PUlQDsyk0qopurojzVe4r5gdXrVyKLLzUXdAk94ClRsmGbMhYQ /A/A== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:dkim-signature; bh=fICrQzaFYEM459MJ2nnqnPELXia71K/hK5uqpC19sIU=; b=N0bZkozA1RJeN/kx1Oe3H2Q8ZMsYDPOVcyOJHFtyddlXenwWW2RPN4nXUIPgJgA7TA 17TfrtRCVAP71X25BqU7evpVNGu4OmJPXfnz6Kvx9XBqMeXRIbzgTO5vX9OHly0cJVmY LsJkKlBos6W9tfPXiv9O0OY5isIvE9tjfpKHMp9mCR6811ZYHcyFFZ0H9+fouSsexBtq HFu8ipeHIkCownvsc+NnBW63JzWuXqnNXy4mIVqOLL8qsICCU73CAvLKt69zdQbqn1Y/ d4A+et/ph/eXNxeurjZASVa7DjiU1dfaKKt3XHY42nH3JYLhqTo8JDhRlJJVkdE/AxeV yZpQ== ARC-Authentication-Results: i=2; gmr-mx.google.com; spf=neutral (google.com: 212.18.0.10 is neither permitted nor denied by domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20210112; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=fICrQzaFYEM459MJ2nnqnPELXia71K/hK5uqpC19sIU=; b=gjrwxOWmxWO5idWPbtBdAWETf/wFRdyg3wg2hcPaEtsienCGOwvYsY+datwf/9hSde qrLArAT6K+oo72ZHMDT2GNx63h0UFHsjKu2T1I6AcrypoQY3TQxTCpA6Gh5rPasRaKnb Ij1H5lhba2jodF6dy3I5iZzbIJ9WlhMfo2viAP1dufxH7PCP9wymqOu4IyMUgaU1hpDs oYSWCF/xgUke4Rythtzi8x73uW+UE+vxjuXiEEh81WyOzloMkHzKyyfffR8mEYObnKVa 7v3l66MyZfRSVYCKFHmCEC3/NppjTETqsfJIK02VKahX51ZzF6cOgk3+RWhQepbDeB0h cbRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=sender:x-gm-message-state:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-spam-checked-in-group:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=fICrQzaFYEM459MJ2nnqnPELXia71K/hK5uqpC19sIU=; b=OX0BfoZczXKptmzyeQltcvz5r9o+yuv67wg/oDSo5g4K2OdBdScC/iiqhysohGoMyO eYtWtZzwVW+jyk0J43s5WB24B92DAc27ZYHkNKL9GPTL0CRvaE9xf2QWUMetoikD4qGa YsMgYwu1reQg+SESTz7THPHG+SngLcwcbse2bgpabg64Kflqc15iM9nn4gr/E63woREr MFFEd3y5Wsw7mCfY7xB6cHFF1o6CXF1ER00kniob+HehAMD07fEH/1xjsf5mtaT/KRbN sPPSorSaIFLcDiAnO1qvXgGIm1s+mRW6Okf9Ws/eOxz8z+3olNu3oxoWQlPbmeNUMNt8 f4tw== Sender: swupdate@googlegroups.com X-Gm-Message-State: AOAM533VIYBrXmLtjN5tNRiwOmm1FNV5Lu8tE6QYRFBsSLkPyDZrU13/ TJBYoq83GfQWlESnhZNJ2NA= X-Google-Smtp-Source: ABdhPJykcGsdlFgTVAS3g9woC3SLTatmralgPDJe0TfaI3DJNJdXXCcAZdyhFen2i2OleJIf/eBigA== X-Received: by 2002:a2e:b88b:: with SMTP id r11mr3343592ljp.330.1635412529150; Thu, 28 Oct 2021 02:15:29 -0700 (PDT) X-BeenThere: swupdate@googlegroups.com Received: by 2002:a05:6512:31d4:: with SMTP id j20ls1737683lfe.2.gmail; Thu, 28 Oct 2021 02:15:28 -0700 (PDT) X-Received: by 2002:a05:6512:3a8f:: with SMTP id q15mr3036885lfu.425.1635412528270; Thu, 28 Oct 2021 02:15:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1635412528; cv=none; d=google.com; s=arc-20160816; b=jNeeLIxHVSIyEYQNtCbmDpj2OddR6V7V8pW1nk/wPsV8a6h8JrS+Bqiojo8qfDNl0w a8eW4oEU3TGQHIY6PpKPcyRr5UM3BPiCMU10mOZXKH7NmltdWqIXeEGRXLqMLNSPxMT7 ntpWfvheKGL6b8mJBYFvJnCvy0lE+w6UXRrJ4Uly1PyNg52C2feV5K5TZ5gKbxCS4EyT NLFhM2/IvHqF/OCGqpkw4UQ2H3ywTRxDkOgO9N60Ru+mqPjNI9zUccN0pmk8ynTL4TEM i7zMBcoQe+bdoXQwtMDZlFe8hkJsd6nDwKXgsdochPtvkx8xRCHTNJYGNSy0W65PwzXR tAcA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from; bh=FEz4+Cir/xhIGmxix1zSQJAhiPd9I3RmzYszEuB9rPo=; b=hpWyiCQNKo+UjtW6Ust2+cSY+NF1EBcIobQecUXb8tT+FGXulfHpI/TzZU38dEguL6 tKur6agn68PWvp6N3A9JHcQAIQl1KJDzPGC2GaK/CtmuxCp+6qkRXsIzmiKwBQLrvLEx F/BP+ZKnd0bTlRp9k/YSpnUuKOJOAFfBXrF7FiepnUaHjS/hWSZAL2EzyCMIjcq/yIC1 sonL0HKZrPm3m9+h6nM1CKFkff176on/muGq+xSIucbDw6NCCUgMPQRXVrvqBtz0kmaQ jIcPBPJ72enLZMsL9+QxRPk7KDH8LZMu57SladiO3D9u2B1Ha1svLKZKif5W5FLNF5Pc jlcg== ARC-Authentication-Results: i=1; gmr-mx.google.com; spf=neutral (google.com: 212.18.0.10 is neither permitted nor denied by domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de Received: from mail-out.m-online.net (mail-out.m-online.net. [212.18.0.10]) by gmr-mx.google.com with ESMTPS id b27si168415ljf.3.2021.10.28.02.15.28 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 28 Oct 2021 02:15:28 -0700 (PDT) Received-SPF: neutral (google.com: 212.18.0.10 is neither permitted nor denied by domain of sbabic@denx.de) client-ip=212.18.0.10; Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 4Hg0Jv4lbyz1s9rD; Thu, 28 Oct 2021 11:15:27 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 4Hg0Jv3tj2z1qqkB; Thu, 28 Oct 2021 11:15:27 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id LIxbpHxsts4A; Thu, 28 Oct 2021 11:15:24 +0200 (CEST) Received: from babic.homelinux.org (host-88-217-136-221.customer.m-online.net [88.217.136.221]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPS; Thu, 28 Oct 2021 11:15:24 +0200 (CEST) Received: from localhost (mail.babic.homelinux.org [127.0.0.1]) by babic.homelinux.org (Postfix) with ESMTP id 8BECF45406CB; Thu, 28 Oct 2021 11:15:24 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at babic.homelinux.org Received: from babic.homelinux.org ([127.0.0.1]) by localhost (mail.babic.homelinux.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id YpuiNLTKcd8j; Thu, 28 Oct 2021 11:15:20 +0200 (CEST) Received: from paperino.fritz.box (paperino.fritz.box [192.168.178.48]) by babic.homelinux.org (Postfix) with ESMTP id 22BC645412F1; Thu, 28 Oct 2021 11:15:17 +0200 (CEST) From: Stefano Babic To: swupdate@googlegroups.com Cc: Stefano Babic Subject: [swupdate] [PATCH 2/3] Add man page for new swupdate-ipc tool Date: Thu, 28 Oct 2021 11:15:12 +0200 Message-Id: <20211028091513.2875447-3-sbabic@denx.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211028091513.2875447-1-sbabic@denx.de> References: <20211028091513.2875447-1-sbabic@denx.de> MIME-Version: 1.0 X-Original-Sender: sbabic@denx.de X-Original-Authentication-Results: gmr-mx.google.com; spf=neutral (google.com: 212.18.0.10 is neither permitted nor denied by domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de Precedence: list Mailing-list: list swupdate@googlegroups.com; contact swupdate+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: swupdate@googlegroups.com X-Google-Group-Id: 605343134186 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , Signed-off-by: Stefano Babic --- doc/source/index.rst | 3 +- doc/source/swupdate-ipc-interface.rst | 441 ++++++++++++++++++++++++ doc/source/swupdate-ipc.rst | 472 +++----------------------- 3 files changed, 494 insertions(+), 422 deletions(-) create mode 100644 doc/source/swupdate-ipc-interface.rst diff --git a/doc/source/index.rst b/doc/source/index.rst index c40cca9b..e20d0824 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -44,7 +44,7 @@ SWUpdate Documentation mongoose.rst suricatta.rst hawkbit-setup.rst - swupdate-ipc.rst + swupdate-ipc-interface.rst progress.rst bindings.rst building-with-yocto.rst @@ -62,6 +62,7 @@ Utilities and tools swupdate-sendtohawkbit.rst swupdate-progress.rst swupdate-sysrestart.rst + swupdate-ipc.rst ############################################ Help and support diff --git a/doc/source/swupdate-ipc-interface.rst b/doc/source/swupdate-ipc-interface.rst new file mode 100644 index 00000000..bf578de0 --- /dev/null +++ b/doc/source/swupdate-ipc-interface.rst @@ -0,0 +1,441 @@ +.. SPDX-FileCopyrightText: 2013-2021 Stefano Babic +.. SPDX-License-Identifier: GPL-2.0-only + +=================================== +SWUpdate: API for external programs +=================================== + +Overview +======== + +SWUpdate contains an integrated web-server to allow remote updating. +However, which protocols are involved during an update is project +specific and differs significantly. Some projects can decide +to use FTP to load an image from an external server, or using +even a proprietary protocol. +The integrated web-server uses this interface. + +SWUpdate has a simple interface to let external programs +to communicate with the installer. Clients can start an upgrade +and stream an image to the installer, querying then for the status +and the final result. The API is at the moment very simple, but it can +easy be extended in the future if new use cases will arise. + +.. _install_api: + +API Description +=============== + +The communication runs via UDS (Unix Domain Socket). The socket is created +at startup by SWUpdate in /tmp/sockinstctrl as per default configuration. +This socket should, however, not be used directly but instead by the Client +Library explained below. + +The exchanged packets are described in network_ipc.h + +:: + + typedef struct { + int magic; + int type; + msgdata data; + } ipc_message; + + +Where the fields have the meaning: + +- magic : a magic number as simple proof of the packet +- type : one of REQ_INSTALL, ACK, NACK, + GET_STATUS, POST_UPDATE, SWUPDATE_SUBPROCESS, SET_AES_KEY +- msgdata : a buffer used by the client to send the image + or by SWUpdate to report back notifications and status. + +The client sends a REQ_INSTALL packet and waits for an answer. +SWUpdate sends back ACK or NACK, if for example an update is already in progress. + +After the ACK, the client sends the whole image as a stream. SWUpdate +expects that all bytes after the ACK are part of the image to be installed. +SWUpdate recognizes the size of the image from the CPIO header. +Any error lets SWUpdate to leave the update state, and further packets +will be ignored until a new REQ_INSTALL will be received. + +.. image:: images/API.png + +It is recommended to use the client library to communicate with SWUpdate. On the lower +level with direct socket communication, it cannot be guaranteed that the structures +will remain compatible in the future. The client library was affected by this issue, too, and it is +changed to accept an opaque interface that will survive API changes. Compatibility +layers could be added on-demand in the future due to API changes. + + +Client Library +============== + +Functions to start an update +---------------------------- +A library simplifies the usage of the IPC making available a way to +start asynchronously an update. + +The library consists of one function and several call-backs. + +:: + + int swupdate_async_start(writedata wr_func, getstatus status_func, + terminated end_func, void *req, ssize_t size) + typedef int (*writedata)(char **buf, int *size); + typedef int (*getstatus)(ipc_message *msg); + typedef int (*terminated)(RECOVERY_STATUS status); + +swupdate_async_start creates a new thread and start the communication with SWUpdate, +triggering for a new update. The wr_func is called to get the image to be installed. +It is responsibility of the callback to provide the buffer and the size of +the chunk of data. + +The getstatus call-back is called after the stream was downloaded to check +how upgrade is going on. It can be omitted if only the result is required. + +The terminated call-back is called when SWUpdate has finished with the result +of the upgrade. + +Example about using this library is in the examples/client directory. + +The `req` structure is casted to void to ensure API compatibility. Am user +should instantiate it as `struct swupdate_request`. This contains fields that can control +the update process: + +:: + + struct swupdate_request { + unsigned int apiversion; + sourcetype source; + int dry_run; + size_t len; + char info[512]; + char software_set[256]; + char running_mode[256]; + }; + +A user should first call `swupdate_prepare_req()` + +:: + + void swupdate_prepare_req(struct swupdate_request *req); + +This fills the request structure with default values. After that, the user can fill the +other fields as: + + - *sourcetype* : one of SOURCE_UNKNOWN, SOURCE_WEBSERVER, + SOURCE_SURICATTA, SOURCE_DOWNLOADER, SOURCE_LOCAL + - *dry_run* : one of RUN_DEFAULT (set from command line), RUN_DRYRUN, RUN_INSTALL. + - *info, len* : a variable length data that can be forwarded to the progress + interface. The installer in SWUpdate does not evaluate it. + - *software_set* and *running_mode* : this allows one to set the `selection` for the update. + +Functions to set AES keys +------------------------- + +The key for decryption can be set with command line parameter (see `-K`), but it is possible +to set it via IPC. In this way, each update could have a different key. + +:: + + int swupdate_set_aes(char *key, char *ivt) + +The key is for AES-256. The length for key and ivt are then defined by the algorithm amd they are passed as ASCII string, so the length *must* be 64 bytes for key and 32 bytes for IVT. + +Functions to control SWUpdate +----------------------------- + +:: + + int ipc_send_cmd(ipc_message *msg); + +ipc_send_cmd is used to send a command to a SWUpdate subprocess (as suricatta). The function is synchron, +that means it clocks until the subprocess has answered with ACK or NACK. This function sets `type` to SWUPDATE_SUBPROCESS. +The caller must then set the other fields in message according to the destination. +The msgdata field is a structure as: + +:: + + struct { + sourcetype source; /* Who triggered the update */ + int cmd; /* Optional encoded command */ + int timeout; /* timeout in seconds if an aswer is expected */ + unsigned int len; /* Len of data valid in buf */ + char buf[2048]; /* + * Buffer that each source can fill + * with additional information + */ + } + +The caller fills `source` with the subprocess that acceps the command. Values of cmd +are in `network_ipc.h`. + +Messages for suricatta +---------------------- + +suricatta accepts messages in JSON format. The message must be formatted in the `buf` field of +the message data. + +Setting the polling time +........................ + +:: + + { "polling" : } + +Setting it to 0 has the special meaning that the polling time is retrieved from the Backend +(if this is supported by the server). + +Enable / disable Suricatta daemon +................................. + +:: + + { "enable" : true } + { "enable" : false } + +Set custom device attributes for Suricatta (for Hawkbit implementation) +....................................................................... + +:: + + { "identify" : [ + { + "name" : "customizableAttributeOne", + "value" : "valueOne" + }, + { + "name" : "customizableAttributeTwo", + "value" : "valueTwo" + } + ]} + +New attributes can be added at runtime, and existing attributes can be modified in the same +way. Changes will be reflected on the server in the next poll iteration. + + +Trigger a check on the server +............................. + +This is useful in case the device is mostly offline, and when it is online, it should check +immediately if an update exists and run it. In fact, after enabling the suricatta daemon, +the update follows the usual states, and the daemon waits for a polling time before +loading the new software. This command forces an update (if available) without changing the +polling time. + +:: + + { "trigger" : true } + + +Activate an already installed Software +...................................... + +After a software was installed, the new software boots and if everything runs fine, +an acknowledge should be sent to the hawkBit server. If this feature is used, for example +to let the end user decide if the new software is accepted, the parameters used by the installation +should be stored during the update process. + +:: + + { "id" : , + "finished" : "success", "failure", "none", + "execution" : ["closed", "proceeding", canceled", "rejected", "resumed"] + "details" : [ ] + } + +Get hawkBit Server Status +......................... + +To provide the hawkBit server status to other processes, it can be requested by +sending an empty message with message type CMD_GET_STATUS. + +The response is a JSON object containing the hawkBit server status . + is a number representing the value of the channel_op_res_t enum from +channel_op_res.h. As the hawkBit server is polled, its status can only be +updated when it has been polled. Therefore the response also contains the +time