1 /*
2 * Copyright (C)2018-2022 Intel Corporation.
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <sys/queue.h>
10 #include <sys/un.h>
11 #include <pthread.h>
12 #include <errno.h>
13 #include <sys/un.h>
14 #include <sys/socket.h>
15 #include <sys/stat.h>
16 #include <dirent.h>
17 #include "mevent.h"
18 #include "acrn_mngr.h"
19
20 /* helpers */
21 /* Check if @path exists and if is a directory, if not existence, create or warn according to the flag */
check_dir(const char * path,int flags)22 int check_dir(const char *path, int flags)
23 {
24 struct stat st;
25
26 if (stat(path, &st)) {
27 if (flags) {
28 if (mkdir(path, 0666)) {
29 perror(path);
30 return -1;
31 }
32 return 0;
33 } else {
34 printf("%s doesn't exist!\n", path);
35 return -1;
36 }
37 }
38
39 if (S_ISDIR(st.st_mode))
40 return 0;
41
42 fprintf(stderr, "%s exist, and not a directory!\n", path);
43 return -1;
44 }
45
46
47 #define MNGR_SOCK_FMT "/run/acrn/mngr/%s.%d.socket"
48 #define MNGR_MAX_HANDLER 8
49 #define MNGR_MAX_CLIENT 4
50
51 #define CLIENT_BUF_LEN 4096
52
53 struct mngr_client {
54 /* the rest should be invisible for msg_handler */
55 struct sockaddr_un addr;
56 int fd;
57 socklen_t addr_len;
58 void *buf;
59 int len; /* buf len */
60 LIST_ENTRY(mngr_client) list;
61 };
62
63 struct mngr_handler {
64 unsigned id;
65 void (*cb) (struct mngr_msg * msg, int client_fd, void *priv);
66 void *priv;
67 LIST_ENTRY(mngr_handler) list;
68 };
69
70 struct mngr_fd {
71 int type;
72 int desc; /* unique int to this descripter */
73 /* returned by mngr_open_un */
74 LIST_ENTRY(mngr_fd) list;
75
76 /* Unix socket stuff */
77 int fd; /* the unix socket fd */
78 struct sockaddr_un addr;
79 socklen_t addr_len;
80
81 /* for servet */
82 int listening;
83 int polling;
84 pthread_t listen_thread; /* for connect/disconnect */
85 pthread_t poll_thread; /* poll requests */
86
87 /* a server can have many client connection */
88 LIST_HEAD(client_list, mngr_client) client_head; /* clients for this server */
89 pthread_mutex_t client_mtx;
90 int num_client;
91
92 /* handlers */
93 LIST_HEAD(handler_list, mngr_handler) handler_head; /* clients for this server */
94 pthread_mutex_t handler_mtx;
95 };
96
mngr_client_new(struct mngr_fd * mfd)97 static struct mngr_client *mngr_client_new(struct mngr_fd *mfd)
98 {
99 struct mngr_client *client;
100
101 client = calloc(1, sizeof(*client));
102 if (!client) {
103 printf("%s: Failed to alloc mem for client\n", __func__);
104 goto alloc_client;
105 }
106
107 client->buf = calloc(1, CLIENT_BUF_LEN);
108 if (!client->buf) {
109 printf("%s: Failed to alloc mem for client buf\n", __func__);
110 goto alloc_buf;
111 }
112
113 client->addr_len = sizeof(client->addr);
114 client->fd =
115 accept(mfd->fd, (struct sockaddr *)&client->addr,
116 &client->addr_len);
117 if (client->fd < 0) {
118 printf("%s: Failed to accept from fd %d, err: %s\n", __func__, mfd->fd, strerror(errno));
119 goto accept_con;
120 }
121
122 pthread_mutex_lock(&mfd->client_mtx);
123 LIST_INSERT_HEAD(&mfd->client_head, client, list);
124 pthread_mutex_unlock(&mfd->client_mtx);
125
126 return client;
127
128 accept_con:
129 free(client->buf);
130 client->buf = NULL;
131 alloc_buf:
132 free(client);
133 alloc_client:
134 return NULL;
135 }
136
mngr_client_free_res(struct mngr_client * client)137 static void mngr_client_free_res(struct mngr_client *client)
138 {
139 close(client->fd);
140 client->fd = -1;
141 free(client->buf);
142 client->buf = NULL;
143 free(client);
144 }
145
mngr_client_free(struct mngr_fd * mfd,struct mngr_client * client)146 static void mngr_client_free(struct mngr_fd *mfd, struct mngr_client *client)
147 {
148 pthread_mutex_lock(&mfd->client_mtx);
149 LIST_REMOVE(client, list);
150 pthread_mutex_unlock(&mfd->client_mtx);
151
152 mngr_client_free_res(client);
153 }
154
155 static LIST_HEAD(mngr_fd_list, mngr_fd) mngr_fd_head;
156 static pthread_mutex_t mngr_fd_mtx = PTHREAD_MUTEX_INITIALIZER;
157
server_listen_func(void * arg)158 static void *server_listen_func(void *arg)
159 {
160 struct mngr_fd *mfd = arg;
161 struct mngr_client *client;
162
163 printf("Listening %d...\n", mfd->desc);
164 while (mfd->listening) {
165 /* wait connection */
166 if (mfd->num_client >= MNGR_MAX_CLIENT) {
167 usleep(500000);
168 continue;
169 }
170
171 client = mngr_client_new(mfd);
172 if (!client) {
173 usleep(500000);
174 continue;
175 }
176 printf("Connected:%d\n", client->fd);
177 mfd->num_client++;
178 }
179 printf("Stop listening %d...\n", mfd->desc);
180 return NULL;
181 }
182
server_parse_buf(struct mngr_fd * mfd,struct mngr_client * client)183 static int server_parse_buf(struct mngr_fd *mfd, struct mngr_client *client)
184 {
185 struct mngr_msg *msg;
186 struct mngr_handler *handler;
187 size_t p = 0;
188 int handled = 0;
189
190 if (client->len < sizeof(struct mngr_msg))
191 return -1;
192
193 do {
194 msg = client->buf + p;
195
196 /* do we out-of-boundary? */
197 if (p + sizeof(struct mngr_msg) > client->len) {
198 printf("%s: Out of boundary, client len: %d, p: %lu\n", __func__, client->len, p);
199 break;
200 }
201
202 LIST_FOREACH(handler, &mfd->handler_head, list) {
203 if (msg->magic != MNGR_MSG_MAGIC)
204 return -1;
205 if (handler->id != msg->msgid)
206 continue;
207
208 handler->cb(msg, client->fd, handler->priv);
209 handled = 1;
210 break;
211 }
212 p += sizeof(struct mngr_msg);
213 } while (p < client->len);
214
215 if (!handled)
216 fprintf(stderr, "Unknown message id: %d\n", msg->msgid);
217
218 return 0;
219 }
220
server_poll_func(void * arg)221 static void *server_poll_func(void *arg)
222 {
223 struct mngr_fd *mfd = arg;
224 struct mngr_client *client;
225 fd_set rfd;
226 int max_fd = 0;
227 struct timeval timeout;
228 struct mngr_client *poll_client[MNGR_MAX_CLIENT];
229 int nfd, i;
230
231 printf("polling %d...\n", mfd->desc);
232 while (mfd->polling) {
233 max_fd = 0;
234 nfd = 0;
235 pthread_mutex_lock(&mfd->client_mtx);
236 FD_ZERO(&rfd);
237 LIST_FOREACH(client, &mfd->client_head, list) {
238 FD_SET(client->fd, &rfd);
239 poll_client[nfd] = client;
240 nfd++;
241 if (client->fd > max_fd)
242 max_fd = client->fd;
243 }
244 pthread_mutex_unlock(&mfd->client_mtx);
245
246 timeout.tv_sec = 0;
247 timeout.tv_usec = 10000;
248 select(max_fd + 1, &rfd, NULL, NULL, &timeout);
249
250 for (i = 0; i < nfd; i++) {
251 client = poll_client[i];
252 if (!FD_ISSET(client->fd, &rfd))
253 continue;
254 client->len =
255 read(client->fd, client->buf, CLIENT_BUF_LEN);
256 if (client->len <= 0) {
257 fprintf(stderr, "Disconnect(%d)!\r\n",
258 client->fd);
259 mngr_client_free(mfd, client);
260 mfd->num_client--;
261 continue;
262 }
263 if (client->len == CLIENT_BUF_LEN) {
264 fprintf(stderr, "TODO: buf overflow!\r\n");
265 continue;
266 }
267
268 server_parse_buf(mfd, client);
269 }
270 }
271 printf("Stop polling %d...\n", mfd->desc);
272
273 return NULL;
274 }
275
desc_to_mfd_nolock(int val)276 static struct mngr_fd *desc_to_mfd_nolock(int val)
277 {
278 struct mngr_fd *fd;
279 struct mngr_fd *find = NULL;
280
281 LIST_FOREACH(fd, &mngr_fd_head, list)
282 if (val == fd->desc) {
283 find = fd;
284 break;
285 }
286
287 return find;
288 }
289
290 /* Does this integer number has a mngr_fd behind? */
desc_to_mfd(int val)291 static struct mngr_fd *desc_to_mfd(int val)
292 {
293 struct mngr_fd *find = NULL;
294
295 pthread_mutex_lock(&mngr_fd_mtx);
296 find = desc_to_mfd_nolock(val);
297 pthread_mutex_unlock(&mngr_fd_mtx);
298
299 return find;
300 }
301
create_new_server(const char * name)302 static int create_new_server(const char *name)
303 {
304 struct mngr_fd *mfd;
305 int ret;
306 char path[128] = { };
307
308 if (snprintf(path, sizeof(path), MNGR_SOCK_FMT, name, getpid()) >= sizeof(path)) {
309 printf("WARN: the path is truncated\n");
310 return -1;
311 }
312
313 mfd = calloc(1, sizeof(*mfd));
314 if (!mfd) {
315 perror("Alloc struct mngr_fd");
316 ret = errno;
317 goto alloc_mfd;
318 }
319 pthread_mutex_init(&mfd->client_mtx, NULL);
320 mfd->type = MNGR_SERVER;
321
322 /* Socket stuff */
323 unlink(path);
324 mfd->fd = socket(AF_UNIX, SOCK_STREAM, 0);
325 if (mfd->fd < 0) {
326 printf("%s: Failed to call socket, err: %s\n", __func__, strerror(errno));
327 ret = mfd->fd;
328 goto sock_err;
329 }
330 mfd->addr.sun_family = AF_UNIX;
331 strncpy(mfd->addr.sun_path, path, sizeof(mfd->addr.sun_path));
332
333 ret = bind(mfd->fd, (struct sockaddr *)&mfd->addr, sizeof(mfd->addr));
334 if (ret < 0) {
335 printf("%s: Failed to bind fd %d, err: %s\n", __func__, mfd->fd, strerror(errno));
336 goto bind_err;
337 }
338 listen(mfd->fd, 1);
339
340 /* create a listen_thread */
341 mfd->listening = 1;
342 ret =
343 pthread_create(&mfd->listen_thread, NULL, server_listen_func, mfd);
344 if (ret < 0) {
345 printf("%s: Failed to create listen_thread, err: %s\n", __func__, strerror(errno));
346 goto listen_err;
347 }
348 pthread_setname_np(mfd->listen_thread, "mngr_listen");
349
350 /* create a poll_thread */
351 mfd->polling = 1;
352 ret = pthread_create(&mfd->poll_thread, NULL, server_poll_func, mfd);
353 if (ret < 0) {
354 printf("%s: Failed to create poll_thread, err: %s\n", __func__, strerror(errno));
355 goto poll_err;
356 }
357 pthread_setname_np(mfd->poll_thread, "mngr_pull");
358
359 mfd->desc = mfd->fd;
360 /* add this to mngr_fd_head */
361 pthread_mutex_lock(&mngr_fd_mtx);
362 LIST_INSERT_HEAD(&mngr_fd_head, mfd, list);
363 pthread_mutex_unlock(&mngr_fd_mtx);
364
365 return mfd->desc;
366
367 poll_err:
368 mfd->listening = 0;
369 pthread_join(mfd->listen_thread, NULL);
370 listen_err:
371 unlink(path);
372 bind_err:
373 close(mfd->fd);
374 sock_err:
375 free(mfd);
376 alloc_mfd:
377 return ret;
378 }
379
close_server(struct mngr_fd * mfd)380 static void close_server(struct mngr_fd *mfd)
381 {
382 struct mngr_client *client, *tclient;
383 struct mngr_handler *handler, *thandler;
384
385 shutdown(mfd->fd, SHUT_RDWR);
386
387 mfd->listening = 0;
388 pthread_join(mfd->listen_thread, NULL);
389
390 mfd->polling = 0;
391 pthread_join(mfd->poll_thread, NULL);
392
393 pthread_mutex_lock(&mfd->client_mtx);
394 list_foreach_safe(client, &mfd->client_head, list, tclient) {
395 LIST_REMOVE(client, list);
396 mngr_client_free_res(client);
397 }
398 pthread_mutex_unlock(&mfd->client_mtx);
399
400 pthread_mutex_lock(&mfd->handler_mtx);
401 list_foreach_safe(handler, &mfd->handler_head, list, thandler) {
402 LIST_REMOVE(handler, list);
403 free(handler);
404 }
405 pthread_mutex_unlock(&mfd->handler_mtx);
406
407 unlink(mfd->addr.sun_path);
408 close(mfd->fd);
409
410 free(mfd);
411 }
412
connect_to_server(const char * name)413 static int connect_to_server(const char *name)
414 {
415 struct mngr_fd *mfd;
416 int ret;
417 DIR *dir;
418 char *s_name = NULL, *p = NULL;
419 struct dirent *entry;
420
421 dir = opendir("/run/acrn/mngr");
422 if (!dir) {
423 printf("%s: Failed to open directory /run/acrn/mngr\n", __func__);
424 return -1;
425 }
426
427 while ((entry = readdir(dir))) {
428 p = strchr(entry->d_name, '.');
429 if (!p || p == entry->d_name)
430 continue;
431 else
432 ret = p - entry->d_name;
433
434 if (!strncmp(entry->d_name, name, ret)) {
435 s_name = entry->d_name;
436 break;
437 }
438 }
439
440 if (!s_name) {
441 printf("%s: Can't find %s\n", __func__, name);
442 closedir(dir);
443 return -1;
444 }
445
446 mfd = calloc(1, sizeof(*mfd));
447 if (!mfd) {
448 perror("Alloc struct mngr_fd");
449 ret = errno;
450 goto alloc_mfd;
451 }
452
453 mfd->fd = socket(AF_UNIX, SOCK_STREAM, 0);
454 if (mfd->fd < 0) {
455 printf("%s %d\n", __FUNCTION__, __LINE__);
456 ret = -1;
457 goto sock_err;
458 }
459
460 mfd->addr.sun_family = AF_UNIX;
461 ret = snprintf(mfd->addr.sun_path, sizeof(mfd->addr.sun_path),
462 "/run/acrn/mngr/%s", s_name);
463 if (ret >= sizeof(mfd->addr.sun_path))
464 printf("WARN: %s is truncated\n", s_name);
465
466 ret =
467 connect(mfd->fd, (struct sockaddr *)&mfd->addr, sizeof(mfd->addr));
468 if (ret < 0) {
469 printf("%s %d\n", __FUNCTION__, __LINE__);
470 goto connect_err;
471 }
472
473 mfd->desc = mfd->fd;
474 /* add this to mngr_fd_head */
475 pthread_mutex_lock(&mngr_fd_mtx);
476 LIST_INSERT_HEAD(&mngr_fd_head, mfd, list);
477 pthread_mutex_unlock(&mngr_fd_mtx);
478
479 closedir(dir);
480 return mfd->desc;
481
482 connect_err:
483 close(mfd->fd);
484 sock_err:
485 free(mfd);
486 alloc_mfd:
487 closedir(dir);
488 return ret;
489 }
490
close_client(struct mngr_fd * mfd)491 static void close_client(struct mngr_fd *mfd)
492 {
493 close(mfd->fd);
494 free(mfd);
495 }
496
mngr_open_un(const char * name,int flags)497 int mngr_open_un(const char *name, int flags)
498 {
499 check_dir(ACRN_DM_BASE_PATH, CHK_ONLY);
500 check_dir(ACRN_DM_SOCK_PATH, CHK_ONLY);
501
502 if (!name) {
503 printf("%s: No socket name configured\n", __func__);
504 return -1;
505 }
506
507 switch (flags) {
508 case MNGR_SERVER:
509 return create_new_server(name);
510 case MNGR_CLIENT:
511 return connect_to_server(name);
512 default:
513 printf("%s: Unknow flag %d\n", __func__, flags);
514 }
515
516 return -1;
517 }
518
mngr_close(int val)519 void mngr_close(int val)
520 {
521 struct mngr_fd *mfd;
522
523 mfd = desc_to_mfd(val);
524 if (!mfd) {
525 printf("%s: No mngr_fd binded to fd %d\n", __func__, val);
526 return;
527 }
528
529 pthread_mutex_lock(&mngr_fd_mtx);
530 LIST_REMOVE(mfd, list);
531 pthread_mutex_unlock(&mngr_fd_mtx);
532
533 switch (mfd->type) {
534 case MNGR_SERVER:
535 close_server(mfd);
536 break;
537 case MNGR_CLIENT:
538 close_client(mfd);
539 break;
540 default:
541 printf("%s: Unknown mfd type %d\n", __func__, mfd->type);
542 }
543
544 }
545
mngr_add_handler(int server_fd,unsigned id,void (* cb)(struct mngr_msg * msg,int client_fd,void * param),void * param)546 int mngr_add_handler(int server_fd, unsigned id,
547 void (*cb) (struct mngr_msg * msg, int client_fd,
548 void *param), void *param)
549 {
550 struct mngr_fd *mfd;
551 struct mngr_handler *handler;
552
553 mfd = desc_to_mfd(server_fd);
554 if (!mfd) {
555 printf("%s: No mngr_fd binded to fd %d\n", __func__, server_fd);
556 return -1;
557 }
558
559 handler = calloc(1, sizeof(*handler));
560 if (!handler) {
561 printf("%s: Failed to alloc mem for handler\n", __func__);
562 return -1;
563 }
564
565 handler->id = id;
566 handler->cb = cb;
567 handler->priv = param;
568
569 pthread_mutex_lock(&mfd->handler_mtx);
570 LIST_INSERT_HEAD(&mfd->handler_head, handler, list);
571 pthread_mutex_unlock(&mfd->handler_mtx);
572
573 return 0;
574 }
575
mngr_send_msg(int fd,struct mngr_msg * req,struct mngr_msg * ack,unsigned timeout)576 int mngr_send_msg(int fd, struct mngr_msg *req, struct mngr_msg *ack,
577 unsigned timeout)
578 {
579 int socket_fd = fd;
580 fd_set rfd, wfd;
581 struct timeval t;
582 int ret;
583
584 if (!req) {
585 printf("%s %d\n", __FUNCTION__, __LINE__);
586 return -1;
587 }
588
589 t.tv_sec = timeout;
590 t.tv_usec = 0;
591
592 FD_ZERO(&rfd);
593 FD_ZERO(&wfd);
594 FD_SET(socket_fd, &rfd);
595 FD_SET(socket_fd, &wfd);
596
597 if (timeout)
598 select(socket_fd + 1, NULL, &wfd, NULL, &t);
599 else
600 select(socket_fd + 1, NULL, &wfd, NULL, NULL);
601
602 if (!FD_ISSET(socket_fd, &wfd)) {
603 printf("%s %d\n", __FUNCTION__, __LINE__);
604 return -1;
605 }
606
607 ret = write(socket_fd, req, sizeof(struct mngr_msg));
608 if (ret != sizeof(struct mngr_msg)) {
609 printf("%s %d\n", __FUNCTION__, __LINE__);
610 return -1;
611 }
612
613 if (!ack)
614 return 0;
615
616 if (timeout)
617 select(socket_fd + 1, &rfd, NULL, NULL, &t);
618 else
619 select(socket_fd + 1, &rfd, NULL, NULL, NULL);
620
621 if (!FD_ISSET(socket_fd, &rfd)) {
622 printf("%s %d\n", __FUNCTION__, __LINE__);
623 return -1;
624 }
625
626 ret = read(socket_fd, ack, sizeof(struct mngr_msg));
627
628 return ret;
629 }
630