+
+static bool
+rpc_validate_sid(const char *id)
+{
+ if (!id)
+ return false;
+
+ if (strlen(id) != RPC_SID_LEN)
+ return false;
+
+ while (*id)
+ if (!isxdigit(*id++))
+ return false;
+
+ return true;
+}
+
+static int
+rpc_blob_to_file(const char *path, struct blob_attr *attr)
+{
+ int fd, len;
+
+ fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0600);
+
+ if (fd < 0)
+ return fd;
+
+ len = write(fd, attr, blob_pad_len(attr));
+
+ close(fd);
+
+ if (len != blob_pad_len(attr))
+ {
+ unlink(path);
+ return -1;
+ }
+
+ return len;
+}
+
+static struct blob_attr *
+rpc_blob_from_file(const char *path)
+{
+ int fd = -1, len;
+ struct stat s;
+ struct blob_attr head, *attr = NULL;
+
+ if (stat(path, &s) || !S_ISREG(s.st_mode))
+ return NULL;
+
+ fd = open(path, O_RDONLY);
+
+ if (fd < 0)
+ goto fail;
+
+ len = read(fd, &head, sizeof(head));
+
+ if (len != sizeof(head) || blob_pad_len(&head) != s.st_size)
+ goto fail;
+
+ attr = calloc(1, s.st_size);
+
+ if (!attr)
+ goto fail;
+
+ memcpy(attr, &head, sizeof(head));
+
+ len += read(fd, (char *)attr + sizeof(head), s.st_size - sizeof(head));
+
+ if (len != blob_pad_len(&head))
+ goto fail;
+
+ return attr;
+
+fail:
+ if (fd >= 0)
+ close(fd);
+
+ if (attr)
+ free(attr);
+
+ return NULL;
+}
+
+static bool
+rpc_session_from_blob(struct blob_attr *attr)
+{
+ int i, rem, rem2, rem3;
+ struct rpc_session *ses;
+ struct blob_attr *tb[__RPC_DUMP_MAX], *scope, *object, *function;
+
+ blobmsg_parse(dump_policy, __RPC_DUMP_MAX, tb,
+ blob_data(attr), blob_len(attr));
+
+ for (i = 0; i < __RPC_DUMP_MAX; i++)
+ if (!tb[i])
+ return false;
+
+ ses = rpc_session_new();
+
+ if (!ses)
+ return false;
+
+ memcpy(ses->id, blobmsg_data(tb[RPC_DUMP_SID]), RPC_SID_LEN);
+
+ ses->timeout = blobmsg_get_u32(tb[RPC_DUMP_TIMEOUT]);
+
+ blobmsg_for_each_attr(scope, tb[RPC_DUMP_ACLS], rem) {
+ blobmsg_for_each_attr(object, scope, rem2) {
+ blobmsg_for_each_attr(function, object, rem3) {
+ rpc_session_grant(ses, NULL, blobmsg_name(scope),
+ blobmsg_name(object),
+ blobmsg_data(function));
+ }
+ }
+ }
+
+ blobmsg_for_each_attr(object, tb[RPC_DUMP_DATA], rem) {
+ rpc_session_set(ses, blobmsg_name(object), object);
+ }
+
+ avl_insert(&sessions, &ses->avl);
+
+ uloop_timeout_set(&ses->t, blobmsg_get_u32(tb[RPC_DUMP_EXPIRES]) * 1000);
+
+ return true;
+}
+