1 /*
2 * Copyright (C) 2022 Intel Corporation.
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdbool.h>
11 #include <string.h>
12 #include <termios.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/socket.h>
17 #include <pthread.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20 #include <sys/un.h>
21 #include <cjson/cJSON.h>
22 #include "socket.h"
23 #include "command.h"
24 #include "vmmapi.h"
25 #include "cmd_monitor.h"
26 #include "log.h"
27 #include "dm.h"
28 #include "command_handler.h"
29
30 struct socket_dev *sock_server; /* socket server instance */
31 static char socket_path[UNIX_SOCKET_PATH_MAX];
32
parse_command(char * cmd_msg,int fd)33 static struct command *parse_command(char *cmd_msg, int fd)
34 {
35 struct command *cmd = NULL;
36 const cJSON *execute;
37 const cJSON *arguments;
38 cJSON *cmd_json;
39
40 cmd_json = cJSON_Parse(cmd_msg);
41 if (cmd_json == NULL) {
42 const char *error_ptr = cJSON_GetErrorPtr();
43 if (error_ptr != NULL) {
44 fprintf(stderr, "Error before: %s\n", error_ptr);
45 }
46 return NULL;
47 }
48 execute = cJSON_GetObjectItemCaseSensitive(cmd_json, "command");
49 if (cJSON_IsString(execute) && (execute->valuestring != NULL)) {
50 pr_info("Command name: \"%s\"\n", execute->valuestring);
51
52 cmd = find_command(execute->valuestring);
53 if (cmd != NULL) {
54 cmd->para.fd = fd;
55 arguments = cJSON_GetObjectItemCaseSensitive(cmd_json, "arguments");
56 if (cJSON_IsString(arguments) && (arguments->valuestring != NULL)) {
57 pr_info("Command arguments: \"%s\"\n", arguments->valuestring);
58 strncpy(cmd->para.option, arguments->valuestring, CMD_ARG_MAX - 1U);
59 }
60 } else {
61 pr_err("Command [%s] is not supported.\n", execute->valuestring);
62 }
63 }
64 cJSON_Delete(cmd_json);
65 return cmd;
66 }
monitor_cmd_dispatch(char * cmd_msg,int fd)67 static void monitor_cmd_dispatch(char *cmd_msg, int fd)
68 {
69 struct command *cmd;
70
71 cmd = parse_command(cmd_msg, fd);
72 if (cmd != NULL) {
73 dispatch_command_handlers(cmd);
74 }
75 return;
76 }
77
init_socket_server(void)78 int init_socket_server(void)
79 {
80 int ret = 0;
81
82 if (strnlen(socket_path, UNIX_SOCKET_PATH_MAX) == 0) {
83 pr_err("Failed to initialize command monitor due to invalid socket path.\n");
84 }
85
86 sock_server = init_socket(socket_path);
87 if (sock_server == NULL)
88 return -1;
89 ret = open_socket(sock_server, monitor_cmd_dispatch);
90 if (ret < 0)
91 return ret;
92 return ret;
93 }
94
register_socket_message_handlers(struct vmctx * ctx)95 static void register_socket_message_handlers(struct vmctx *ctx)
96 {
97 struct handler_args arg;
98 arg.channel_arg = sock_server;
99 arg.ctx_arg = ctx;
100 register_command_handler(user_vm_destroy_handler, &arg, DESTROY);
101 register_command_handler(user_vm_blkrescan_handler, &arg, BLKRESCAN);
102 register_command_handler(user_vm_register_vm_event_client_handler, &arg, REGISTER_VM_EVENT_CLIENT);
103 }
104
init_cmd_monitor(struct vmctx * ctx)105 int init_cmd_monitor(struct vmctx *ctx)
106 {
107 int ret;
108 ret = init_socket_server();
109 register_socket_message_handlers(ctx);
110 return ret;
111 }
deinit_cmd_monitor(void)112 void deinit_cmd_monitor(void)
113 {
114 if (sock_server != NULL) {
115 close_socket(sock_server);
116 deinit_socket(sock_server);
117 }
118 }
acrn_parse_cmd_monitor(char * arg)119 int acrn_parse_cmd_monitor(char *arg)
120 {
121 int err = -1;
122 size_t len = strnlen(arg, UNIX_SOCKET_PATH_MAX);
123
124 if (len < UNIX_SOCKET_PATH_MAX) {
125 strncpy(socket_path, arg, len + 1);
126 pr_notice("Command monitor: using soket path %s\n", socket_path);
127 err = 0;
128 }
129 return err;
130 }
131