/* $OpenBSD: var-config.c,v 1.3 2019/11/28 18:40:42 kn Exp $ */ /* * Copyright (c) 2012 Mark Kettenis * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include "ds.h" #include "mdesc.h" #include "ldom_util.h" #include "ldomd.h" void var_config_start(struct ldc_conn *, uint64_t); void var_config_rx_data(struct ldc_conn *, uint64_t, void *, size_t); struct ds_service var_config_service = { "var-config", 1, 0, var_config_start, var_config_rx_data }; #define VAR_CONFIG_SET_REQ 0x00 #define VAR_CONFIG_DELETE_REQ 0x01 struct var_config_set_req { uint32_t msg_type; uint32_t payload_len; uint64_t svc_handle; uint32_t cmd; char name[1]; } __packed; #define VAR_CONFIG_SET_RESP 0x02 #define VAR_CONFIG_DELETE_RESP 0x03 struct var_config_resp { uint32_t msg_type; uint32_t payload_len; uint64_t svc_handle; uint32_t cmd; uint32_t result; } __packed; #define VAR_CONFIG_SUCCESS 0x00 #define VAR_CONFIG_NO_SPACE 0x01 #define VAR_CONFIG_INVALID_VAR 0x02 #define VAR_CONFIG_INVALID_VAL 0x03 #define VAR_CONFIG_VAR_NOT_PRESENT 0x04 uint32_t set_variable(struct guest *guest, const char *name, const char *value) { struct md *md = guest->md; struct md_node *node; struct md_prop *prop; node = md_find_node(md, "variables"); if (node == NULL) { struct md_node *root = md_find_node(md, "root"); assert(root); node = md_add_node(md, "variables"); md_link_node(md, root, node); } prop = md_add_prop_str(md, node, name, value); if (prop == NULL) return VAR_CONFIG_NO_SPACE; hv_update_md(guest); return VAR_CONFIG_SUCCESS; } uint32_t delete_variable(struct guest *guest, const char *name) { struct md *md = guest->md; struct md_node *node; struct md_prop *prop; node = md_find_node(md, "variables"); if (node == NULL) return VAR_CONFIG_VAR_NOT_PRESENT; prop = md_find_prop(md, node, name); if (prop == NULL) return VAR_CONFIG_VAR_NOT_PRESENT; md_delete_prop(md, node, prop); hv_update_md(guest); return VAR_CONFIG_SUCCESS; } void var_config_start(struct ldc_conn *lc, uint64_t svc_handle) { } void var_config_rx_data(struct ldc_conn *lc, uint64_t svc_handle, void *data, size_t len) { struct ds_conn *dc = lc->lc_cookie; struct var_config_set_req *vr = data; struct var_config_resp vx; switch (vr->cmd) { case VAR_CONFIG_SET_REQ: vx.msg_type = DS_DATA; vx.payload_len = sizeof(vx) - 8; vx.svc_handle = svc_handle; vx.cmd = VAR_CONFIG_SET_RESP; vx.result = set_variable(dc->cookie, vr->name, vr->name + strlen(vr->name) + 1); ds_send_msg(lc, &vx, sizeof(vx)); break; case VAR_CONFIG_DELETE_REQ: vx.msg_type = DS_DATA; vx.payload_len = sizeof(vx) - 8; vx.svc_handle = svc_handle; vx.result = delete_variable(dc->cookie, vr->name); vx.cmd = VAR_CONFIG_DELETE_RESP; ds_send_msg(lc, &vx, sizeof(vx)); break; default: printf("Unknown request 0x%02x\n", vr->cmd); break; } }