// ubus call test_ubus helloworld '{"id":1,"msg":"hello","array":["a","b"]}' static int test_hello(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct blob_attr *tb[__HELLO_MAX]; int tmp_id; char *tmp_msg = NULL; int len; struct blob_attr *attr; void *arr; blobmsg_parse(hello_policy, __HELLO_MAX, tb, blob_data(msg), blob_len(msg)); blob_buf_init(&b, 0); if(tb[HELLO_ID]) { tmp_id = blobmsg_get_u32(tb[HELLO_ID]); blobmsg_add_u32(&b, "id", tmp_id); } if(tb[HELLO_MSG]) { tmp_msg = blobmsg_get_string(tb[HELLO_MSG]); blobmsg_add_string(&b, "msg", tmp_msg); } if(tb[HELLO_ARRAY] && blobmsg_type(tb[HELLO_ARRAY]) == BLOBMSG_TYPE_ARRAY) { arr = blobmsg_open_array(&b, "array"); len = blobmsg_data_len(tb[HELLO_ARRAY]); __blob_for_each_attr(attr, blobmsg_data(tb[HELLO_ARRAY]), len) { if (blobmsg_type(attr) == BLOBMSG_TYPE_STRING) { char *tmp = blobmsg_get_string(attr); blobmsg_add_blob(&b, attr); printf("array=%s\n", tmp); } } blobmsg_close_array(&b, arr); }
static int rpc_juci_backup_config_set(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { FILE *f; struct blob_attr *tb[__RPC_D_MAX]; blobmsg_parse(rpc_data_policy, __RPC_D_MAX, tb, blob_data(msg), blob_len(msg)); if (!tb[RPC_D_DATA]) return UBUS_STATUS_INVALID_ARGUMENT; if (blobmsg_data_len(tb[RPC_D_DATA]) >= 2048) return UBUS_STATUS_NOT_SUPPORTED; if (!(f = fopen("/etc/sysupgrade.conf", "w"))) return rpc_errno_status(); fwrite(blobmsg_data(tb[RPC_D_DATA]), blobmsg_data_len(tb[RPC_D_DATA]) - 1, 1, f); fclose(f); return 0; }
static int service_update(struct service *s, struct blob_attr **tb, bool add) { struct blob_attr *cur; int rem; if (s->trigger) { trigger_del(s); free(s->trigger); s->trigger = NULL; } service_validate_del(s); if (tb[SERVICE_SET_TRIGGER] && blobmsg_data_len(tb[SERVICE_SET_TRIGGER])) { s->trigger = blob_memdup(tb[SERVICE_SET_TRIGGER]); if (!s->trigger) return -1; trigger_add(s->trigger, s); } if (tb[SERVICE_SET_VALIDATE] && blobmsg_data_len(tb[SERVICE_SET_VALIDATE])) { blobmsg_for_each_attr(cur, tb[SERVICE_SET_VALIDATE], rem) service_validate_add(s, cur); } if (tb[SERVICE_SET_INSTANCES]) { if (!add) vlist_update(&s->instances); blobmsg_for_each_attr(cur, tb[SERVICE_SET_INSTANCES], rem) { service_instance_add(s, cur); } if (!add) vlist_flush(&s->instances); }
bool blobmsg_check_attr(const struct blob_attr *attr, bool name) { const struct blobmsg_hdr *hdr; const char *data; int id, len; if (blob_len(attr) < sizeof(struct blobmsg_hdr)) return false; hdr = (void *) attr->data; if (!hdr->namelen && name) return false; if (blobmsg_namelen(hdr) > blob_len(attr) - sizeof(struct blobmsg_hdr)) return false; if (hdr->name[blobmsg_namelen(hdr)] != 0) return false; id = blob_id(attr); len = blobmsg_data_len(attr); data = blobmsg_data(attr); if (!id || id > BLOBMSG_TYPE_LAST) return false; if (!blob_type[id]) return true; return blob_check_type(data, len, blob_type[id]); }
void blobmsg_format_std_indent(const struct blob_attr *data, int indent) { struct blob_attr *attr; const struct blob_attr *head = blobmsg_data(data); int len = blobmsg_data_len(data); __blob_for_each_attr(attr, head, len) { int type = blobmsg_type(attr); if (blobmsg_type(data) != BLOBMSG_TYPE_ARRAY && blobmsg_name(attr)[0]) indent_printf(indent, "%s: ", blobmsg_name(attr)); else indent_printf(indent, "%s", ""); if (type == BLOBMSG_TYPE_TABLE) printf("{\n"); else if (type == BLOBMSG_TYPE_ARRAY) printf("[\n"); blobmsg_format_element(attr, indent + 1); if (type == BLOBMSG_TYPE_TABLE) indent_printf(indent, "}\n"); else if (type == BLOBMSG_TYPE_ARRAY) indent_printf(indent, "]\n"); }
static void parse_subnets(struct list_head *head, enum fw3_family family, struct blob_attr *list) { struct blob_attr *cur; struct fw3_address *addr; int rem; if (!list) return; rem = blobmsg_data_len(list); __blob_for_each_attr(cur, blobmsg_data(list), rem) { addr = parse_subnet(family, blobmsg_data(cur), blobmsg_data_len(cur)); if (addr) list_add_tail(&addr->list, head); }
static void dump_table(struct blob_attr *head, int len, int indent, bool array) { struct blob_attr *attr; struct blobmsg_hdr *hdr; indent_printf(indent, "{\n"); __blob_for_each_attr(attr, head, len) { hdr = blob_data(attr); if (!array) indent_printf(indent + 1, "%s : ", hdr->name); dump_attr_data(blobmsg_data(attr), blobmsg_data_len(attr), blob_id(attr), 0, indent + 1); }
static int rpc_juci_backup_restore(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct blob_attr *tb[__RPC_BACKUP_MAX]; blobmsg_parse(rpc_backup_policy, __RPC_BACKUP_MAX, tb, blob_data(msg), blob_len(msg)); struct blob_attr *pass = tb[RPC_BACKUP_PASSWORD]; if (pass && blobmsg_data_len(pass) > 0 && blobmsg_data(pass) && strlen(blobmsg_data(pass)) > 0){ const char *cmd[] = { "sysupgrade", "--restore-backup", "/tmp/backup.tar.gz", "--password", blobmsg_data(pass), NULL }; return ops->exec(cmd, NULL, NULL, NULL, NULL, NULL, ctx, req); } const char *cmd[] = { "sysupgrade", "--restore-backup", "/tmp/backup.tar.gz", NULL }; return ops->exec(cmd, NULL, NULL, NULL, NULL, NULL, ctx, req); }
static struct device_addr * parse_address_item(struct blob_attr *attr, bool v6, bool ext) { struct device_addr *addr; struct blob_attr *tb[__ADDR_MAX]; struct blob_attr *cur; if (blobmsg_type(attr) != BLOBMSG_TYPE_TABLE) return NULL; addr = alloc_device_addr(v6, ext); if (!addr) return NULL; blobmsg_parse(proto_ip_addr, __ADDR_MAX, tb, blobmsg_data(attr), blobmsg_data_len(attr)); addr->mask = v6 ? 128 : 32; if ((cur = tb[ADDR_MASK])) { unsigned int new_mask; new_mask = parse_netmask_string(blobmsg_data(cur), v6); if (new_mask > addr->mask) goto error; addr->mask = new_mask; } cur = tb[ADDR_IPADDR]; if (!cur) goto error; if (!inet_pton(v6 ? AF_INET6 : AF_INET, blobmsg_data(cur), &addr->addr)) goto error; if ((cur = tb[ADDR_OFFLINK]) && blobmsg_get_bool(cur)) addr->flags |= DEVADDR_OFFLINK; if (!v6) { if ((cur = tb[ADDR_BROADCAST]) && !inet_pton(AF_INET, blobmsg_data(cur), &addr->broadcast)) goto error; if ((cur = tb[ADDR_PTP]) && !inet_pton(AF_INET, blobmsg_data(cur), &addr->point_to_point)) goto error; } else { time_t now = system_get_rtime(); if ((cur = tb[ADDR_PREFERRED])) { int64_t preferred = blobmsg_get_u32(cur); int64_t preferred_until = preferred + (int64_t)now; if (preferred_until <= LONG_MAX && preferred != 0xffffffffLL) addr->preferred_until = preferred_until; } if ((cur = tb[ADDR_VALID])) { int64_t valid = blobmsg_get_u32(cur); int64_t valid_until = valid + (int64_t)now; if (valid_until <= LONG_MAX && valid != 0xffffffffLL) addr->valid_until = valid_until; } if (addr->valid_until) { if (!addr->preferred_until) addr->preferred_until = addr->valid_until; else if (addr->preferred_until > addr->valid_until) goto error; } if ((cur = tb[ADDR_CLASS])) addr->pclass = strdup(blobmsg_get_string(cur)); } return addr; error: free(addr); return NULL; }
static int rpc_rrdns_lookup(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { int port = 53, limit = RRDNS_DEF_LIMIT, timeout = RRDNS_DEF_TIMEOUT; struct blob_attr *tb[__RPC_L_MAX]; struct rrdns_context *rctx; const char *server = NULL; blobmsg_parse(rpc_lookup_policy, __RPC_L_MAX, tb, blob_data(msg), blob_len(msg)); if (tb[RPC_L_PORT]) port = blobmsg_get_u16(tb[RPC_L_PORT]); if (tb[RPC_L_LIMIT]) limit = blobmsg_get_u32(tb[RPC_L_LIMIT]); if (tb[RPC_L_TIMEOUT]) timeout = blobmsg_get_u32(tb[RPC_L_TIMEOUT]); if (tb[RPC_L_SERVER]) server = blobmsg_get_string(tb[RPC_L_SERVER]); if (!tb[RPC_L_ADDRS]) return UBUS_STATUS_INVALID_ARGUMENT; if (port <= 0) return UBUS_STATUS_INVALID_ARGUMENT; if (limit <= 0 || limit > RRDNS_MAX_LIMIT) return UBUS_STATUS_INVALID_ARGUMENT; if (timeout <= 0 || timeout > RRDNS_MAX_TIMEOUT) return UBUS_STATUS_INVALID_ARGUMENT; if (!server || !*server) server = rrdns_find_nameserver(); if (!server) return UBUS_STATUS_NOT_FOUND; rctx = calloc(1, sizeof(*rctx)); if (!rctx) return UBUS_STATUS_UNKNOWN_ERROR; rctx->socket.fd = usock(USOCK_UDP, server, usock_port(port)); if (rctx->socket.fd < 0) { free(rctx); return UBUS_STATUS_UNKNOWN_ERROR; } rctx->context = ctx; rctx->addr_cur = blobmsg_data(tb[RPC_L_ADDRS]); rctx->addr_rem = blobmsg_data_len(tb[RPC_L_ADDRS]); avl_init(&rctx->request_ids, rrdns_cmp_id, false, NULL); avl_init(&rctx->request_addrs, rrdns_cmp_addr, false, NULL); rctx->timeout.cb = rrdns_handle_timeout; uloop_timeout_set(&rctx->timeout, timeout); rctx->socket.cb = rrdns_handle_response; uloop_fd_add(&rctx->socket, ULOOP_READ); blob_buf_init(&rctx->blob, 0); while (limit--) rrdns_next_query(rctx); ubus_defer_request(ctx, req, &rctx->request); return UBUS_STATUS_OK; }
void iprule_add(struct blob_attr *attr, bool v6) { struct interface *iif = NULL, *oif = NULL; struct blob_attr *tb[__RULE_MAX], *cur; struct interface *iface; struct iprule *rule; int af = v6 ? AF_INET6 : AF_INET; blobmsg_parse(rule_attr, __RULE_MAX, tb, blobmsg_data(attr), blobmsg_data_len(attr)); rule = calloc(1, sizeof(*rule)); if (!rule) return; rule->flags = v6 ? IPRULE_INET6 : IPRULE_INET4; rule->order = iprules_counter[rule->flags]++; if ((cur = tb[RULE_INVERT]) != NULL) rule->invert = blobmsg_get_bool(cur); if ((cur = tb[RULE_INTERFACE_IN]) != NULL) { iif = vlist_find(&interfaces, blobmsg_data(cur), iface, node); if (!iif || !iif->l3_dev.dev) { DPRINTF("Failed to resolve device of network: %s\n", (char *) blobmsg_data(cur)); goto error; } memcpy(rule->in_dev, iif->l3_dev.dev->ifname, sizeof(rule->in_dev)); rule->flags |= IPRULE_IN; } if ((cur = tb[RULE_INTERFACE_OUT]) != NULL) { oif = vlist_find(&interfaces, blobmsg_data(cur), iface, node); if (!oif || !oif->l3_dev.dev) { DPRINTF("Failed to resolve device of network: %s\n", (char *) blobmsg_data(cur)); goto error; } memcpy(rule->out_dev, oif->l3_dev.dev->ifname, sizeof(rule->out_dev)); rule->flags |= IPRULE_OUT; } if ((cur = tb[RULE_SRC]) != NULL) { if (!parse_ip_and_netmask(af, blobmsg_data(cur), &rule->src_addr, &rule->src_mask)) { DPRINTF("Failed to parse rule source: %s\n", (char *) blobmsg_data(cur)); goto error; } rule->flags |= IPRULE_SRC; } if ((cur = tb[RULE_DEST]) != NULL) { if (!parse_ip_and_netmask(af, blobmsg_data(cur), &rule->dest_addr, &rule->dest_mask)) { DPRINTF("Failed to parse rule destination: %s\n", (char *) blobmsg_data(cur)); goto error; } rule->flags |= IPRULE_DEST; } if ((cur = tb[RULE_PRIORITY]) != NULL) { rule->priority = blobmsg_get_u32(cur); rule->flags |= IPRULE_PRIORITY; } if ((cur = tb[RULE_TOS]) != NULL) { if ((rule->tos = blobmsg_get_u32(cur)) > 255) { DPRINTF("Invalid TOS value: %u\n", blobmsg_get_u32(cur)); goto error; } rule->flags |= IPRULE_TOS; } if ((cur = tb[RULE_FWMARK]) != NULL) { if (!iprule_parse_mark(blobmsg_data(cur), rule)) { DPRINTF("Failed to parse rule fwmark: %s\n", (char *) blobmsg_data(cur)); goto error; } /* flags set by iprule_parse_mark() */ } if ((cur = tb[RULE_LOOKUP]) != NULL) { if (!system_resolve_rt_table(blobmsg_data(cur), &rule->lookup)) { DPRINTF("Failed to parse rule lookup table: %s\n", (char *) blobmsg_data(cur)); goto error; } rule->flags |= IPRULE_LOOKUP; } if ((cur = tb[RULE_ACTION]) != NULL) { if (!system_resolve_iprule_action(blobmsg_data(cur), &rule->action)) { DPRINTF("Failed to parse rule action: %s\n", (char *) blobmsg_data(cur)); goto error; } rule->flags |= IPRULE_ACTION; } if ((cur = tb[RULE_GOTO]) != NULL) { rule->gotoid = blobmsg_get_u32(cur); rule->flags |= IPRULE_GOTO; } vlist_add(&iprules, &rule->node, &rule->flags); return; error: free(rule); }