1 /*
2 * Copyright (C) 2022 Intel Corporation.
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <stdbool.h>
9 #include <unistd.h>
10 #include <netinet/in.h>
11 #include <arpa/inet.h>
12 #include <sys/un.h>
13 #include <libgen.h>
14 #include <cjson/cJSON.h>
15 #include "command.h"
16 #include "socket.h"
17 #include "command_handler.h"
18 #include "dm.h"
19 #include "pm.h"
20 #include "vmmapi.h"
21 #include "log.h"
22 #include "monitor.h"
23
24 #define SUCCEEDED 0
25 #define FAILED -1
26
generate_ack_message(int ret_val)27 static char *generate_ack_message(int ret_val)
28 {
29 char *ack_msg;
30 cJSON *val;
31 cJSON *ret_obj = cJSON_CreateObject();
32
33 if (ret_obj == NULL)
34 return NULL;
35 val = cJSON_CreateNumber(ret_val);
36 if (val == NULL)
37 return NULL;
38 cJSON_AddItemToObject(ret_obj, "ack", val);
39 ack_msg = cJSON_Print(ret_obj);
40 if (ack_msg == NULL)
41 fprintf(stderr, "Failed to generate ACK message.\n");
42 cJSON_Delete(ret_obj);
43 return ack_msg;
44 }
send_socket_ack(struct socket_dev * sock,int fd,bool normal)45 static int send_socket_ack(struct socket_dev *sock, int fd, bool normal)
46 {
47 int ret = 0, val;
48 char *ack_message;
49 struct socket_client *client = NULL;
50
51 client = find_socket_client(sock, fd);
52 if (client == NULL)
53 return -1;
54 val = normal ? SUCCEEDED : FAILED;
55 ack_message = generate_ack_message(val);
56
57 if (ack_message != NULL) {
58 memset(client->buf, 0, CLIENT_BUF_LEN);
59 memcpy(client->buf, ack_message, strlen(ack_message));
60 client->len = strlen(ack_message);
61 ret = write_socket_char(client);
62 free(ack_message);
63 } else {
64 pr_err("Failed to generate ACK message.\n");
65 ret = -1;
66 }
67 return ret;
68 }
69
70 static struct socket_client *vm_event_client = NULL;
71 static pthread_mutex_t vm_event_client_mutex = PTHREAD_MUTEX_INITIALIZER;
72
vm_event_free_cb(struct socket_client * self)73 static void vm_event_free_cb(struct socket_client *self)
74 {
75 vm_event_client = NULL;
76 }
77
set_vm_event_client(struct socket_client * client)78 static int set_vm_event_client(struct socket_client *client)
79 {
80 if (vm_event_client != NULL) {
81 pr_err("vm event client already registerred.\n");
82 return -1;
83 } else {
84 vm_event_client = client;
85 client->per_client_mutex = &vm_event_client_mutex;
86 client->free_client_cb = vm_event_free_cb;
87 return 0;
88 }
89 }
90
vm_monitor_send_vm_event(const char * msg)91 int vm_monitor_send_vm_event(const char *msg)
92 {
93 int ret = -1;
94 struct socket_client *client;
95 pthread_mutex_t *per_client_mutex = &vm_event_client_mutex;
96
97 pthread_mutex_lock(per_client_mutex);
98 client = vm_event_client;
99 if (msg == NULL || client == NULL) {
100 pthread_mutex_unlock(per_client_mutex);
101 return -1;
102 }
103 memset(client->buf, 0, CLIENT_BUF_LEN);
104 memcpy(client->buf, msg, strlen(msg));
105 client->len = strlen(msg);
106 ret = write_socket_char(client);
107 pthread_mutex_unlock(per_client_mutex);
108 return ret;
109 }
110
111 /* When a client issues the REGISTER_VM_EVENT_CLIENT command,
112 * this handler will register that client as this VM's only vm_event receiver,
113 * and keeps the socket connection. Then vm events will be sent to
114 * the client through this connection.
115 */
user_vm_register_vm_event_client_handler(void * arg,void * command_para)116 int user_vm_register_vm_event_client_handler(void *arg, void *command_para)
117 {
118 int ret;
119 struct command_parameters *cmd_para = (struct command_parameters *)command_para;
120 struct handler_args *hdl_arg = (struct handler_args *)arg;
121 struct socket_dev *sock = (struct socket_dev *)hdl_arg->channel_arg;
122 struct socket_client *client = NULL;
123 bool cmd_completed = false;
124
125 client = find_socket_client(sock, cmd_para->fd);
126 if (client == NULL)
127 return -1;
128
129 if (set_vm_event_client(client) == 0) {
130 cmd_completed = true;
131 }
132
133 pr_dbg("%s: client with fd %d registerred\n", __func__, client->fd);
134
135 ret = send_socket_ack(sock, cmd_para->fd, cmd_completed);
136 if (ret < 0) {
137 pr_err("%s: Failed to send ACK message by socket.\n", __func__);
138 }
139 return ret;
140 }
141
user_vm_destroy_handler(void * arg,void * command_para)142 int user_vm_destroy_handler(void *arg, void *command_para)
143 {
144 int ret;
145 struct command_parameters *cmd_para = (struct command_parameters *)command_para;
146 struct handler_args *hdl_arg = (struct handler_args *)arg;
147 struct socket_dev *sock = (struct socket_dev *)hdl_arg->channel_arg;
148 struct socket_client *client = NULL;
149 bool cmd_completed = false;
150
151 client = find_socket_client(sock, cmd_para->fd);
152 if (client == NULL)
153 return -1;
154
155 if (!is_rtvm) {
156 pr_info("%s: setting VM state to %s.\n", __func__, vm_state_to_str(VM_SUSPEND_POWEROFF));
157 vm_set_suspend_mode(VM_SUSPEND_POWEROFF);
158 cmd_completed = true;
159 } else {
160 pr_err("Failed to destroy post-launched RTVM.\n");
161 ret = -1;
162 }
163
164 ret = send_socket_ack(sock, cmd_para->fd, cmd_completed);
165 if (ret < 0) {
166 pr_err("Failed to send ACK message by socket.\n");
167 }
168 return ret;
169 }
170
user_vm_blkrescan_handler(void * arg,void * command_para)171 int user_vm_blkrescan_handler(void *arg, void *command_para)
172 {
173 int ret = 0;
174 struct command_parameters *cmd_para = (struct command_parameters *)command_para;
175 struct handler_args *hdl_arg = (struct handler_args *)arg;
176 struct socket_dev *sock = (struct socket_dev *)hdl_arg->channel_arg;
177 struct socket_client *client = NULL;
178 bool cmd_completed = false;
179
180 client = find_socket_client(sock, cmd_para->fd);
181 if (client == NULL)
182 return -1;
183
184 ret = vm_monitor_blkrescan(hdl_arg->ctx_arg, cmd_para->option);
185 if (ret >= 0) {
186 cmd_completed = true;
187 } else {
188 pr_err("Failed to rescan virtio-blk device.\n");
189 }
190
191 ret = send_socket_ack(sock, cmd_para->fd, cmd_completed);
192 if (ret < 0) {
193 pr_err("Failed to send ACK by socket.\n");
194 }
195 return ret;
196 }
197