auc: update to version 0.0.9
* use full package list when checking for upgrades * verify sha256sums and usign signature of sha256sums.sig * introduce '-c' option to only check if system is up-to-date * introduce '-F' option to ignore the signature verification result * return -1 on locally caused and -2 on server-side errors * don't include locally appended attributes in debug output of a server reply * output bug report note on 412 target not found * use content-length header instead of filesize field in JSON content * suppress duplicate error messages * drop unused attributes * make debug messages optional at compile-time Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
parent
2be807285a
commit
8162fecb37
|
@ -5,8 +5,8 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=auc
|
||||
PKG_VERSION:=0.0.8
|
||||
PKG_RELEASE=1
|
||||
PKG_VERSION:=0.0.9
|
||||
PKG_RELEASE:=1
|
||||
PKG_LICENSE:=GPL-3.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
@ -24,6 +24,12 @@ define Package/auc/description
|
|||
CLI client for attended-sysupgrade
|
||||
endef
|
||||
|
||||
# set to 1 to enable debugging
|
||||
DEBUG:=1
|
||||
|
||||
EXTRA_CFLAGS += \
|
||||
$(if $(DEBUG),-DAUC_DEBUG=ON)
|
||||
|
||||
define Package/auc/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/auc $(1)/usr/sbin/
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define AUC_VERSION "0.0.8"
|
||||
#define AUC_VERSION "0.0.9"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <dlfcn.h>
|
||||
|
@ -39,6 +39,16 @@
|
|||
#define APIOBJ_CHECK "api/upgrade-check"
|
||||
#define APIOBJ_REQUEST "api/upgrade-request"
|
||||
|
||||
#define PUBKEY_PATH "/etc/opkg/keys"
|
||||
|
||||
#ifdef AUC_DEBUG
|
||||
#define DPRINTF(...) if (debug) fprintf(stderr, __VA_ARGS__)
|
||||
#else
|
||||
#define DPRINTF(...)
|
||||
#endif
|
||||
|
||||
static const char server_issues[]="https://github.com/aparcar/attendedsysupgrade-server/issues";
|
||||
|
||||
static char user_agent[80];
|
||||
static char *serverurl;
|
||||
static int upgrade_packages;
|
||||
|
@ -52,30 +62,26 @@ static int output_fd = -1;
|
|||
static int retry, imagebuilder, building, ibready;
|
||||
static char *board_name = NULL;
|
||||
static char *target = NULL, *subtarget = NULL;
|
||||
static char *distribution = NULL, *version = NULL, *revision = NULL;
|
||||
static char *distribution = NULL, *version = NULL;
|
||||
static int uptodate;
|
||||
static char *filename = NULL;
|
||||
static int rc;
|
||||
|
||||
#ifdef AUC_DEBUG
|
||||
static int debug = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* policy for ubus call system board
|
||||
* see procd/system.c
|
||||
*/
|
||||
enum {
|
||||
BOARD_KERNEL,
|
||||
BOARD_HOSTNAME,
|
||||
BOARD_SYSTEM,
|
||||
BOARD_MODEL,
|
||||
BOARD_BOARD_NAME,
|
||||
BOARD_RELEASE,
|
||||
__BOARD_MAX,
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy board_policy[__BOARD_MAX] = {
|
||||
[BOARD_KERNEL] = { .name = "kernel", .type = BLOBMSG_TYPE_STRING },
|
||||
[BOARD_HOSTNAME] = { .name = "hostname", .type = BLOBMSG_TYPE_STRING },
|
||||
[BOARD_SYSTEM] = { .name = "system", .type = BLOBMSG_TYPE_STRING },
|
||||
[BOARD_MODEL] = { .name = "model", .type = BLOBMSG_TYPE_STRING },
|
||||
[BOARD_BOARD_NAME] = { .name = "board_name", .type = BLOBMSG_TYPE_STRING },
|
||||
[BOARD_RELEASE] = { .name = "release", .type = BLOBMSG_TYPE_TABLE },
|
||||
};
|
||||
|
@ -87,20 +93,14 @@ static const struct blobmsg_policy board_policy[__BOARD_MAX] = {
|
|||
enum {
|
||||
RELEASE_DISTRIBUTION,
|
||||
RELEASE_VERSION,
|
||||
RELEASE_REVISION,
|
||||
RELEASE_CODENAME,
|
||||
RELEASE_TARGET,
|
||||
RELEASE_DESCRIPTION,
|
||||
__RELEASE_MAX,
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy release_policy[__RELEASE_MAX] = {
|
||||
[RELEASE_DISTRIBUTION] = { .name = "distribution", .type = BLOBMSG_TYPE_STRING },
|
||||
[RELEASE_VERSION] = { .name = "version", .type = BLOBMSG_TYPE_STRING },
|
||||
[RELEASE_REVISION] = { .name = "revision", .type = BLOBMSG_TYPE_STRING },
|
||||
[RELEASE_CODENAME] = { .name = "codename", .type = BLOBMSG_TYPE_STRING },
|
||||
[RELEASE_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
|
||||
[RELEASE_DESCRIPTION] = { .name = "description", .type = BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -146,6 +146,11 @@ static const struct blobmsg_policy check_policy[__CHECK_MAX] = {
|
|||
[CHECK_UPGRADES] = { .name = "upgrades", .type = BLOBMSG_TYPE_TABLE },
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy pkg_upgrades_policy[2] = {
|
||||
{ .type = BLOBMSG_TYPE_STRING },
|
||||
{ .type = BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
|
||||
/*
|
||||
* policy for upgrade-request response
|
||||
* parse download information for the ready image.
|
||||
|
@ -162,19 +167,37 @@ enum {
|
|||
|
||||
static const struct blobmsg_policy image_policy[__IMAGE_MAX] = {
|
||||
[IMAGE_REQHASH] = { .name = "request_hash", .type = BLOBMSG_TYPE_STRING },
|
||||
[IMAGE_FILESIZE] = { .name = "filesize", .type = BLOBMSG_TYPE_INT32 },
|
||||
[IMAGE_URL] = { .name = "url", .type = BLOBMSG_TYPE_STRING },
|
||||
[IMAGE_CHECKSUM] = { .name = "checksum", .type = BLOBMSG_TYPE_STRING },
|
||||
[IMAGE_FILES] = { .name = "files", .type = BLOBMSG_TYPE_STRING },
|
||||
[IMAGE_SYSUPGRADE] = { .name = "sysupgrade", .type = BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
|
||||
/*
|
||||
* policy for HTTP headers received from server
|
||||
*/
|
||||
enum {
|
||||
H_RANGE,
|
||||
H_LEN,
|
||||
H_IBSTATUS,
|
||||
H_IBQUEUEPOS,
|
||||
H_UNKNOWN_PACKAGE,
|
||||
__H_MAX
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy policy[__H_MAX] = {
|
||||
[H_RANGE] = { .name = "content-range", .type = BLOBMSG_TYPE_STRING },
|
||||
[H_LEN] = { .name = "content-length", .type = BLOBMSG_TYPE_STRING },
|
||||
[H_IBSTATUS] = { .name = "x-imagebuilder-status", .type = BLOBMSG_TYPE_STRING },
|
||||
[H_IBQUEUEPOS] = { .name = "x-build-queue-position", .type = BLOBMSG_TYPE_STRING },
|
||||
[H_UNKNOWN_PACKAGE] = { .name = "x-unknown-package", .type = BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
|
||||
/*
|
||||
* load serverurl from UCI
|
||||
*/
|
||||
static int load_config() {
|
||||
static struct uci_context *uci_ctx;
|
||||
static struct uci_package *uci_attendedsysupgrade;
|
||||
struct uci_context *uci_ctx;
|
||||
struct uci_package *uci_attendedsysupgrade;
|
||||
struct uci_section *uci_s;
|
||||
|
||||
uci_ctx = uci_alloc_context();
|
||||
|
@ -217,20 +240,47 @@ static int load_config() {
|
|||
* rpc-sys packagelist
|
||||
* append packagelist response to blobbuf given in req->priv
|
||||
*/
|
||||
static void pkglist_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
|
||||
static void pkglist_check_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
|
||||
struct blob_buf *buf = (struct blob_buf *)req->priv;
|
||||
struct blob_attr *tb[__PACKAGELIST_MAX];
|
||||
|
||||
blobmsg_parse(packagelist_policy, __PACKAGELIST_MAX, tb, blob_data(msg), blob_len(msg));
|
||||
|
||||
if (!tb[PACKAGELIST_PACKAGES]) {
|
||||
fprintf(stderr, "No packagelist received\n");
|
||||
rc=-1;
|
||||
return;
|
||||
}
|
||||
|
||||
blobmsg_add_field(buf, BLOBMSG_TYPE_TABLE, "packages", blobmsg_data(tb[PACKAGELIST_PACKAGES]), blobmsg_data_len(tb[PACKAGELIST_PACKAGES]));
|
||||
};
|
||||
|
||||
/*
|
||||
* rpc-sys packagelist
|
||||
* append array of package names to blobbuf given in req->priv
|
||||
*/
|
||||
static void pkglist_req_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
|
||||
struct blob_buf *buf = (struct blob_buf *)req->priv;
|
||||
struct blob_attr *tb[__PACKAGELIST_MAX];
|
||||
struct blob_attr *cur;
|
||||
int rem;
|
||||
void *array;
|
||||
|
||||
blobmsg_parse(packagelist_policy, __PACKAGELIST_MAX, tb, blob_data(msg), blob_len(msg));
|
||||
|
||||
if (!tb[PACKAGELIST_PACKAGES]) {
|
||||
fprintf(stderr, "No packagelist received\n");
|
||||
return;
|
||||
}
|
||||
|
||||
blobmsg_add_field(buf, BLOBMSG_TYPE_TABLE, "packages", blobmsg_data(tb[PACKAGELIST_PACKAGES]), blobmsg_data_len(tb[PACKAGELIST_PACKAGES]));
|
||||
array = blobmsg_open_array(buf, "packages");
|
||||
blobmsg_for_each_attr(cur, tb[PACKAGELIST_PACKAGES], rem)
|
||||
blobmsg_add_string(buf, NULL, blobmsg_name(cur));
|
||||
|
||||
blobmsg_close_array(buf, array);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* system board
|
||||
* append append board information to blobbuf given in req->priv
|
||||
|
@ -245,12 +295,14 @@ static void board_cb(struct ubus_request *req, int type, struct blob_attr *msg)
|
|||
|
||||
if (!tb[BOARD_BOARD_NAME]) {
|
||||
fprintf(stderr, "No board name received\n");
|
||||
rc=-1;
|
||||
return;
|
||||
}
|
||||
board_name = strdup(blobmsg_get_string(tb[BOARD_BOARD_NAME]));
|
||||
|
||||
if (!tb[BOARD_RELEASE]) {
|
||||
fprintf(stderr, "No release received\n");
|
||||
rc=-1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -259,6 +311,7 @@ static void board_cb(struct ubus_request *req, int type, struct blob_attr *msg)
|
|||
|
||||
if (!rel[RELEASE_TARGET]) {
|
||||
fprintf(stderr, "No target received\n");
|
||||
rc=-1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -268,7 +321,6 @@ static void board_cb(struct ubus_request *req, int type, struct blob_attr *msg)
|
|||
|
||||
distribution = strdup(blobmsg_get_string(rel[RELEASE_DISTRIBUTION]));
|
||||
version = strdup(blobmsg_get_string(rel[RELEASE_VERSION]));
|
||||
revision = strdup(blobmsg_get_string(rel[RELEASE_REVISION]));
|
||||
|
||||
blobmsg_add_string(buf, "distro", distribution);
|
||||
blobmsg_add_string(buf, "target", target);
|
||||
|
@ -354,19 +406,6 @@ static void request_done(struct uclient *cl)
|
|||
|
||||
static void header_done_cb(struct uclient *cl)
|
||||
{
|
||||
enum {
|
||||
H_RANGE,
|
||||
H_LEN,
|
||||
H_IBSTATUS,
|
||||
H_IBQUEUEPOS,
|
||||
__H_MAX
|
||||
};
|
||||
static const struct blobmsg_policy policy[__H_MAX] = {
|
||||
[H_RANGE] = { .name = "content-range", .type = BLOBMSG_TYPE_STRING },
|
||||
[H_LEN] = { .name = "content-length", .type = BLOBMSG_TYPE_STRING },
|
||||
[H_IBSTATUS] = { .name = "x-imagebuilder-status", .type = BLOBMSG_TYPE_STRING },
|
||||
[H_IBQUEUEPOS] = { .name = "x-build-queue-position", .type = BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
struct blob_attr *tb[__H_MAX];
|
||||
uint64_t resume_offset = 0, resume_end, resume_size;
|
||||
char *ibstatus;
|
||||
|
@ -385,21 +424,24 @@ static void header_done_cb(struct uclient *cl)
|
|||
return;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
fprintf(stderr, "headers:\n%s\n", blobmsg_format_json_indent(cl->meta, true, 0));
|
||||
DPRINTF("headers:\n%s\n", blobmsg_format_json_indent(cl->meta, true, 0));
|
||||
|
||||
blobmsg_parse(policy, __H_MAX, tb, blob_data(cl->meta), blob_len(cl->meta));
|
||||
|
||||
switch (cl->status_code) {
|
||||
case 400:
|
||||
request_done(cl);
|
||||
rc=-1;
|
||||
break;
|
||||
case 412:
|
||||
fprintf(stderr, "target not found.\n");
|
||||
fprintf(stderr, "%s target %s/%s (%s) not found. Please report this at %s\n",
|
||||
distribution, target, subtarget, board_name, server_issues);
|
||||
request_done(cl);
|
||||
rc=-2;
|
||||
break;
|
||||
case 413:
|
||||
fprintf(stderr, "image too big.\n");
|
||||
rc=-1;
|
||||
request_done(cl);
|
||||
break;
|
||||
case 416:
|
||||
|
@ -407,16 +449,20 @@ static void header_done_cb(struct uclient *cl)
|
|||
request_done(cl);
|
||||
break;
|
||||
case 422:
|
||||
fprintf(stderr, "unknown package requested.\n");
|
||||
fprintf(stderr, "unknown package '%s' requested.\n",
|
||||
blobmsg_get_string(tb[H_UNKNOWN_PACKAGE]));
|
||||
rc=-1;
|
||||
request_done(cl);
|
||||
break;
|
||||
case 501:
|
||||
fprintf(stderr, "ImageBuilder didn't produce sysupgrade file.\n");
|
||||
rc=-2;
|
||||
request_done(cl);
|
||||
break;
|
||||
case 204:
|
||||
fprintf(stderr, "system is up to date.\n");
|
||||
fprintf(stdout, "system is up to date.\n");
|
||||
uptodate=1;
|
||||
request_done(cl);
|
||||
break;
|
||||
case 206:
|
||||
if (!cur_resume) {
|
||||
|
@ -467,6 +513,7 @@ static void header_done_cb(struct uclient *cl)
|
|||
retry=1;
|
||||
} else {
|
||||
fprintf(stderr, "unrecognized remote imagebuilder status '%s'\n", ibstatus);
|
||||
rc=-2;
|
||||
}
|
||||
// fall through
|
||||
case 200:
|
||||
|
@ -657,45 +704,95 @@ static int init_ustream_ssl(void) {
|
|||
}
|
||||
|
||||
/**
|
||||
* use busybox md5sum (from jow's luci-ng)
|
||||
* use busybox sha256sum to verify sha256sums file
|
||||
*/
|
||||
static char *md5sum(const char *file) {
|
||||
static int sha256sum_v(const char *sha256file, const char *msgfile) {
|
||||
pid_t pid;
|
||||
int fds[2];
|
||||
static char md5[33];
|
||||
int status;
|
||||
FILE *f = fopen(sha256file, "r");
|
||||
char sumline[512] = {};
|
||||
char *fname;
|
||||
unsigned int fnlen;
|
||||
unsigned int cnt = 0;
|
||||
|
||||
if (pipe(fds))
|
||||
return NULL;
|
||||
return -1;
|
||||
|
||||
switch ((pid = fork()))
|
||||
{
|
||||
if (!f)
|
||||
return -1;
|
||||
|
||||
|
||||
pid = fork();
|
||||
switch (pid) {
|
||||
case -1:
|
||||
return NULL;
|
||||
return -1;
|
||||
|
||||
case 0:
|
||||
uloop_done();
|
||||
|
||||
dup2(fds[1], 1);
|
||||
|
||||
close(0);
|
||||
dup2(fds[0], 0);
|
||||
close(1);
|
||||
close(2);
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
|
||||
if (execl("/bin/busybox", "/bin/busybox", "md5sum", file, NULL));
|
||||
return NULL;
|
||||
if (execl("/bin/busybox", "/bin/busybox", "sha256sum", "-s", "-c", NULL));
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
memset(md5, 0, sizeof(md5));
|
||||
read(fds[0], md5, 32);
|
||||
waitpid(pid, NULL, 0);
|
||||
close(fds[0]);
|
||||
while (fgets(sumline, sizeof(sumline), f)) {
|
||||
fname = &sumline[66];
|
||||
fnlen = strlen(fname);
|
||||
fname[fnlen-1] = '\0';
|
||||
if (!strcmp(fname, msgfile)) {
|
||||
fname[fnlen-1] = '\n';
|
||||
write(fds[1], sumline, strlen(sumline));
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
close(fds[1]);
|
||||
waitpid(pid, &status, 0);
|
||||
close(fds[0]);
|
||||
|
||||
if (cnt == 1)
|
||||
return WEXITSTATUS(status);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
return md5;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* use usign to verify sha256sums.sig
|
||||
*/
|
||||
static int usign_v(const char *file) {
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
pid = fork();
|
||||
switch (pid) {
|
||||
case -1:
|
||||
return -1;
|
||||
|
||||
case 0:
|
||||
uloop_done();
|
||||
|
||||
if (execl("/usr/bin/usign", "/usr/bin/usign",
|
||||
"-V", "-q", "-P", PUBKEY_PATH, "-m", file, NULL));
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
waitpid(pid, &status, 0);
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ask_user(void)
|
||||
|
@ -711,13 +808,8 @@ static void print_package_updates(struct blob_attr *upgrades) {
|
|||
struct blob_attr *tb[2];
|
||||
int rem;
|
||||
|
||||
static struct blobmsg_policy policy[2] = {
|
||||
{ .type = BLOBMSG_TYPE_STRING },
|
||||
{ .type = BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
|
||||
blobmsg_for_each_attr(cur, upgrades, rem) {
|
||||
blobmsg_parse_array(policy, ARRAY_SIZE(policy), tb, blobmsg_data(cur), blobmsg_data_len(cur));
|
||||
blobmsg_parse_array(pkg_upgrades_policy, ARRAY_SIZE(policy), tb, blobmsg_data(cur), blobmsg_data_len(cur));
|
||||
if (!tb[0] || !tb[1])
|
||||
continue;
|
||||
|
||||
|
@ -728,19 +820,19 @@ static void print_package_updates(struct blob_attr *upgrades) {
|
|||
|
||||
/* this main function is too big... todo: split */
|
||||
int main(int args, char *argv[]) {
|
||||
unsigned char argc=1;
|
||||
static struct blob_buf checkbuf, reqbuf, imgbuf, upgbuf;
|
||||
static struct blob_buf allpkg, checkbuf, infobuf, reqbuf, imgbuf, upgbuf;
|
||||
struct ubus_context *ctx = ubus_connect(NULL);
|
||||
uint32_t id;
|
||||
int rc;
|
||||
int queuepos, valid, use_get;
|
||||
int valid, use_get;
|
||||
char url[256];
|
||||
char *newversion = NULL;
|
||||
struct blob_attr *tb[__IMAGE_MAX];
|
||||
struct blob_attr *tbc[__CHECK_MAX];
|
||||
unsigned int filesize;
|
||||
char *checksum = NULL;
|
||||
char *tmp;
|
||||
struct stat imgstat;
|
||||
int check_only = 0;
|
||||
int ignore_sig = 0;
|
||||
unsigned char argc = 1;
|
||||
|
||||
snprintf(user_agent, sizeof(user_agent), "%s (%s)", argv[0], AUC_VERSION);
|
||||
fprintf(stdout, "%s\n", user_agent);
|
||||
|
@ -750,12 +842,25 @@ int main(int args, char *argv[]) {
|
|||
!strncmp(argv[argc], "--help", 7)) {
|
||||
fprintf(stdout, "%s: Attended sysUpgrade CLI client\n", argv[0]);
|
||||
fprintf(stdout, "Usage: auc [-d] [-h]\n");
|
||||
fprintf(stdout, " -c\tonly check if system is up-to-date\n");
|
||||
fprintf(stdout, " -F\tignore result of signature verification\n");
|
||||
#ifdef AUC_DEBUG
|
||||
fprintf(stdout, " -d\tenable debugging output\n");
|
||||
#endif
|
||||
fprintf(stdout, " -h\toutput help\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef AUC_DEBUG
|
||||
if (!strncmp(argv[argc], "-d", 3))
|
||||
debug = 1;
|
||||
#endif
|
||||
if (!strncmp(argv[argc], "-c", 3))
|
||||
check_only = 1;
|
||||
|
||||
if (!strncmp(argv[argc], "-F", 3))
|
||||
ignore_sig = 1;
|
||||
|
||||
argc++;
|
||||
};
|
||||
|
||||
|
@ -787,9 +892,12 @@ int main(int args, char *argv[]) {
|
|||
}
|
||||
|
||||
blobmsg_buf_init(&checkbuf);
|
||||
blobmsg_buf_init(&infobuf);
|
||||
blobmsg_buf_init(&reqbuf);
|
||||
blobmsg_buf_init(&imgbuf);
|
||||
blobmsg_buf_init(&upgbuf);
|
||||
/* ubus requires BLOBMSG_TYPE_UNSPEC */
|
||||
blob_buf_init(&allpkg, 0);
|
||||
blob_buf_init(&upgbuf, 0);
|
||||
|
||||
if (ubus_lookup_id(ctx, "system", &id) ||
|
||||
ubus_invoke(ctx, id, "board", NULL, board_cb, &checkbuf, 3000)) {
|
||||
|
@ -798,34 +906,37 @@ int main(int args, char *argv[]) {
|
|||
goto freebufs;
|
||||
}
|
||||
|
||||
if (rc)
|
||||
goto freebufs;
|
||||
|
||||
blobmsg_add_u8(&allpkg, "all", 1);
|
||||
blobmsg_add_string(&allpkg, "dummy", "foo");
|
||||
if (ubus_lookup_id(ctx, "rpc-sys", &id) ||
|
||||
ubus_invoke(ctx, id, "packagelist", NULL, pkglist_cb, &checkbuf, 3000)) {
|
||||
ubus_invoke(ctx, id, "packagelist", allpkg.head, pkglist_check_cb, &checkbuf, 3000)) {
|
||||
fprintf(stderr, "cannot request packagelist from rpcd\n");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
|
||||
if (rc)
|
||||
goto freeboard;
|
||||
|
||||
blobmsg_add_u32(&checkbuf, "upgrade_packages", upgrade_packages);
|
||||
|
||||
fprintf(stdout, "running %s %s %s on %s/%s (%s)\n", distribution,
|
||||
version, revision, target, subtarget, board_name);
|
||||
fprintf(stdout, "running %s %s on %s/%s (%s)\n", distribution,
|
||||
version, target, subtarget, board_name);
|
||||
|
||||
fprintf(stdout, "checking %s for release upgrade%s\n", serverurl,
|
||||
upgrade_packages?" or updated packages":"");
|
||||
|
||||
blobmsg_add_string(&reqbuf, "distro", distribution);
|
||||
blobmsg_add_string(&reqbuf, "target", target);
|
||||
blobmsg_add_string(&reqbuf, "subtarget", subtarget);
|
||||
blobmsg_add_string(&reqbuf, "board", board_name);
|
||||
|
||||
snprintf(url, sizeof(url), "%s/%s", serverurl, APIOBJ_CHECK);
|
||||
uptodate=0;
|
||||
|
||||
do {
|
||||
retry=0;
|
||||
if (debug)
|
||||
fprintf(stderr, "requesting:\n%s\n", blobmsg_format_json_indent(checkbuf.head, true, 0));
|
||||
if (server_request(url, &checkbuf, &reqbuf)) {
|
||||
DPRINTF("requesting:\n%s\n", blobmsg_format_json_indent(checkbuf.head, true, 0));
|
||||
if (server_request(url, &checkbuf, &infobuf)) {
|
||||
fprintf(stderr, "failed to connect to server\n");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
|
@ -835,20 +946,20 @@ int main(int args, char *argv[]) {
|
|||
sleep(3);
|
||||
} while(retry);
|
||||
|
||||
if (debug)
|
||||
fprintf(stderr, "reply:\n%s\n", blobmsg_format_json_indent(reqbuf.head, true, 0));
|
||||
DPRINTF("reply:\n%s\n", blobmsg_format_json_indent(infobuf.head, true, 0));
|
||||
|
||||
blobmsg_parse(check_policy, __CHECK_MAX, tbc, blob_data(reqbuf.head), blob_len(reqbuf.head));
|
||||
blobmsg_parse(check_policy, __CHECK_MAX, tbc, blob_data(infobuf.head), blob_len(infobuf.head));
|
||||
|
||||
if (!tbc[CHECK_VERSION] && !tbc[CHECK_UPGRADES]) {
|
||||
if (!uptodate) {
|
||||
if (uptodate) {
|
||||
rc=0;
|
||||
} else if (!rc) {
|
||||
fprintf(stderr, "server reply invalid.\n");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
rc=-2;
|
||||
}
|
||||
rc=0;
|
||||
goto freeboard;
|
||||
}
|
||||
|
||||
if (tbc[CHECK_VERSION]) {
|
||||
newversion = blobmsg_get_string(tbc[CHECK_VERSION]);
|
||||
fprintf(stdout, "new %s release %s found.\n", distribution, newversion);
|
||||
|
@ -862,10 +973,29 @@ int main(int args, char *argv[]) {
|
|||
print_package_updates(tbc[CHECK_UPGRADES]);
|
||||
}
|
||||
|
||||
if (check_only) {
|
||||
rc=1;
|
||||
goto freeboard;
|
||||
};
|
||||
|
||||
rc = ask_user();
|
||||
if (rc)
|
||||
goto freeboard;
|
||||
|
||||
blobmsg_add_string(&reqbuf, "distro", distribution);
|
||||
blobmsg_add_string(&reqbuf, "target", target);
|
||||
blobmsg_add_string(&reqbuf, "subtarget", subtarget);
|
||||
blobmsg_add_string(&reqbuf, "board", board_name);
|
||||
|
||||
blob_buf_init(&allpkg, 0);
|
||||
blobmsg_add_u8(&allpkg, "all", 0);
|
||||
blobmsg_add_string(&allpkg, "dummy", "foo");
|
||||
if (ubus_invoke(ctx, id, "packagelist", allpkg.head, pkglist_req_cb, &reqbuf, 3000)) {
|
||||
fprintf(stderr, "cannot request packagelist from rpcd\n");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
|
||||
snprintf(url, sizeof(url), "%s/%s", serverurl, APIOBJ_REQUEST);
|
||||
|
||||
imagebuilder = 0;
|
||||
|
@ -875,8 +1005,7 @@ int main(int args, char *argv[]) {
|
|||
do {
|
||||
retry = 0;
|
||||
|
||||
if (debug && !use_get)
|
||||
fprintf(stderr, "requesting:\n%s\n", blobmsg_format_json_indent(reqbuf.head, true, 0));
|
||||
DPRINTF("requesting:\n%s\n", use_get?"":blobmsg_format_json_indent(reqbuf.head, true, 0));
|
||||
|
||||
server_request(url, use_get?NULL:&reqbuf, &imgbuf);
|
||||
blobmsg_parse(image_policy, __IMAGE_MAX, tb, blob_data(imgbuf.head), blob_len(imgbuf.head));
|
||||
|
@ -885,9 +1014,7 @@ int main(int args, char *argv[]) {
|
|||
snprintf(url, sizeof(url), "%s/%s/%s", serverurl,
|
||||
APIOBJ_REQUEST,
|
||||
blobmsg_get_string(tb[IMAGE_REQHASH]));
|
||||
if (debug)
|
||||
fprintf(stderr, "polling via GET %s\n", url);
|
||||
|
||||
DPRINTF("polling via GET %s\n", url);
|
||||
retry=1;
|
||||
use_get=1;
|
||||
}
|
||||
|
@ -897,35 +1024,22 @@ int main(int args, char *argv[]) {
|
|||
blobmsg_buf_init(&imgbuf);
|
||||
sleep(3);
|
||||
}
|
||||
} while(retry || queuepos);
|
||||
} while(retry);
|
||||
|
||||
if (debug)
|
||||
fprintf(stderr, "reply:\n%s\n", blobmsg_format_json_indent(imgbuf.head, true, 0));
|
||||
DPRINTF("reply:\n%s\n", blobmsg_format_json_indent(imgbuf.head, true, 0));
|
||||
|
||||
if (!tb[IMAGE_SYSUPGRADE]) {
|
||||
fprintf(stderr, "no sysupgrade image returned\n");
|
||||
rc=-1;
|
||||
if (!rc) {
|
||||
fprintf(stderr, "no sysupgrade image returned\n");
|
||||
rc=-1;
|
||||
}
|
||||
goto freeboard;
|
||||
}
|
||||
|
||||
strncpy(url, blobmsg_get_string(tb[IMAGE_SYSUPGRADE]), sizeof(url));
|
||||
|
||||
if (!tb[IMAGE_FILESIZE]) {
|
||||
fprintf(stderr, "no image size returned\n");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
filesize = blobmsg_get_u32(tb[IMAGE_FILESIZE]);
|
||||
|
||||
if (!tb[IMAGE_CHECKSUM]) {
|
||||
fprintf(stderr, "no image checksum returned\n");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
checksum = blobmsg_get_string(tb[IMAGE_CHECKSUM]);
|
||||
server_request(url, NULL, NULL);
|
||||
/* usign signature is not yet implemented! */
|
||||
// strncat(url, ".sig", sizeof(url));
|
||||
// server_request(url, NULL, NULL);
|
||||
|
||||
filename = uclient_get_url_filename(url, "firmware.bin");
|
||||
|
||||
if (stat(filename, &imgstat)) {
|
||||
|
@ -934,18 +1048,78 @@ int main(int args, char *argv[]) {
|
|||
goto freeboard;
|
||||
}
|
||||
|
||||
if ((intmax_t)imgstat.st_size != filesize) {
|
||||
if ((intmax_t)imgstat.st_size != out_len) {
|
||||
fprintf(stderr, "file size mismatch\n");
|
||||
unlink(filename);
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
|
||||
if (strncmp(checksum, md5sum(filename), 33)) {
|
||||
fprintf(stderr, "image checksum mismatch\n");
|
||||
unlink(filename);
|
||||
tmp=strrchr(url, '/');
|
||||
|
||||
strcpy(tmp, "/sha256sums");
|
||||
server_request(url, NULL, NULL);
|
||||
|
||||
if (stat("sha256sums", &imgstat)) {
|
||||
fprintf(stderr, "sha256sums download failed\n");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
|
||||
if ((intmax_t)imgstat.st_size != out_len) {
|
||||
fprintf(stderr, "sha256sums download incomplete\n");
|
||||
unlink("sha256sums");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
|
||||
if (out_len < 68) {
|
||||
fprintf(stderr, "sha256sums size mismatch\n");
|
||||
unlink("sha256sums");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
|
||||
if (sha256sum_v("sha256sums", filename)) {
|
||||
fprintf(stderr, "checksum verification failed\n");
|
||||
unlink(filename);
|
||||
unlink("sha256sums");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
|
||||
strcpy(tmp, "/sha256sums.sig");
|
||||
server_request(url, NULL, NULL);
|
||||
|
||||
if (stat("sha256sums.sig", &imgstat)) {
|
||||
fprintf(stderr, "sha256sums.sig download failed\n");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
|
||||
if ((intmax_t)imgstat.st_size != out_len) {
|
||||
fprintf(stderr, "sha256sums.sig download incomplete\n");
|
||||
unlink("sha256sums.sig");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
|
||||
if (out_len < 16) {
|
||||
fprintf(stderr, "sha256sums.sig size mismatch\n");
|
||||
unlink("sha256sums.sig");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
|
||||
if (usign_v("sha256sums")) {
|
||||
fprintf(stderr, "signature verification failed\n");
|
||||
if (!ignore_sig) {
|
||||
unlink(filename);
|
||||
unlink("sha256sums");
|
||||
unlink("sha256sums.sig");
|
||||
rc=-1;
|
||||
goto freeboard;
|
||||
}
|
||||
};
|
||||
|
||||
if (strcmp(filename, "firmware.bin")) {
|
||||
|
@ -974,10 +1148,10 @@ freeboard:
|
|||
/* subtarget is a pointer within target, don't free */
|
||||
free(distribution);
|
||||
free(version);
|
||||
free(revision);
|
||||
|
||||
freebufs:
|
||||
blob_buf_free(&checkbuf);
|
||||
blob_buf_free(&infobuf);
|
||||
blob_buf_free(&reqbuf);
|
||||
blob_buf_free(&imgbuf);
|
||||
blob_buf_free(&upgbuf);
|
||||
|
|
Loading…
Reference in New Issue