1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ 2 3 #define _GNU_SOURCE 4 5 #ifdef HAVE_CONFIG_H 6 #include "config.h" 7 #endif 8 9 #define SD_LISTEN_FDS_START 3 10 11 #include "compiler.h" 12 #include "libmctp.h" 13 #include "libmctp-serial.h" 14 #include "libmctp-astlpc.h" 15 #include "utils/mctp-capture.h" 16 17 #include <assert.h> 18 #include <err.h> 19 #include <errno.h> 20 #include <getopt.h> 21 #include <limits.h> 22 #include <poll.h> 23 #include <signal.h> 24 #include <stdbool.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <unistd.h> 29 30 #include <sys/signalfd.h> 31 #include <sys/socket.h> 32 #include <sys/un.h> 33 34 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 35 36 #if HAVE_SYSTEMD_SD_DAEMON_H 37 #include <systemd/sd-daemon.h> 38 #else sd_listen_fds(int i __unused)39 static inline int sd_listen_fds(int i __unused) 40 { 41 return -1; 42 } 43 #endif 44 45 static const mctp_eid_t local_eid_default = 8; 46 static char sockname[] = "\0mctp-mux"; 47 48 struct binding { 49 const char *name; 50 int (*init)(struct mctp *mctp, struct binding *binding, mctp_eid_t eid, 51 int n_params, char *const *params); 52 void (*destroy)(struct mctp *mctp, struct binding *binding); 53 int (*init_pollfd)(struct binding *binding, struct pollfd *pollfd); 54 int (*process)(struct binding *binding); 55 void *data; 56 }; 57 58 struct client { 59 bool active; 60 int sock; 61 uint8_t type; 62 }; 63 64 struct ctx { 65 struct mctp *mctp; 66 struct binding *binding; 67 bool verbose; 68 int local_eid; 69 uint8_t *buf; 70 size_t buf_size; 71 72 int sock; 73 struct pollfd *pollfds; 74 75 struct client *clients; 76 int n_clients; 77 78 struct { 79 struct capture binding; 80 struct capture socket; 81 } pcap; 82 }; 83 tx_message(struct ctx * ctx,mctp_eid_t eid,void * msg,size_t len)84 static void tx_message(struct ctx *ctx, mctp_eid_t eid, void *msg, size_t len) 85 { 86 int rc; 87 88 rc = mctp_message_tx(ctx->mctp, eid, MCTP_MESSAGE_TO_SRC, 0, msg, len); 89 if (rc) 90 warnx("Failed to send message: %d", rc); 91 } 92 client_remove_inactive(struct ctx * ctx)93 static void client_remove_inactive(struct ctx *ctx) 94 { 95 int i; 96 97 for (i = 0; i < ctx->n_clients; i++) { 98 struct client *client = &ctx->clients[i]; 99 if (client->active) 100 continue; 101 close(client->sock); 102 103 ctx->n_clients--; 104 memmove(&ctx->clients[i], &ctx->clients[i + 1], 105 (ctx->n_clients - i) * sizeof(*ctx->clients)); 106 ctx->clients = realloc(ctx->clients, 107 ctx->n_clients * sizeof(*ctx->clients)); 108 } 109 } 110 rx_message(uint8_t eid,bool tag_owner __unused,uint8_t msg_tag __unused,void * data,void * msg,size_t len)111 static void rx_message(uint8_t eid, bool tag_owner __unused, 112 uint8_t msg_tag __unused, void *data, void *msg, 113 size_t len) 114 { 115 struct ctx *ctx = data; 116 struct iovec iov[2]; 117 struct msghdr msghdr; 118 bool removed; 119 uint8_t type; 120 int i, rc; 121 122 if (len < 2) 123 return; 124 125 type = *(uint8_t *)msg; 126 127 if (ctx->verbose) 128 fprintf(stderr, "MCTP message received: len %zd, type %d\n", 129 len, type); 130 131 memset(&msghdr, 0, sizeof(msghdr)); 132 msghdr.msg_iov = iov; 133 msghdr.msg_iovlen = 2; 134 iov[0].iov_base = &eid; 135 iov[0].iov_len = 1; 136 iov[1].iov_base = msg; 137 iov[1].iov_len = len; 138 139 for (i = 0; i < ctx->n_clients; i++) { 140 struct client *client = &ctx->clients[i]; 141 142 if (client->type != type) 143 continue; 144 145 if (ctx->verbose) 146 fprintf(stderr, " forwarding to client %d\n", i); 147 148 rc = sendmsg(client->sock, &msghdr, 0); 149 if (rc != (ssize_t)(len + 1)) { 150 client->active = false; 151 removed = true; 152 } 153 } 154 155 if (removed) 156 client_remove_inactive(ctx); 157 } 158 binding_null_init(struct mctp * mctp __unused,struct binding * binding __unused,mctp_eid_t eid __unused,int n_params,char * const * params __unused)159 static int binding_null_init(struct mctp *mctp __unused, 160 struct binding *binding __unused, 161 mctp_eid_t eid __unused, int n_params, 162 char *const *params __unused) 163 { 164 if (n_params != 0) { 165 warnx("null binding doesn't accept parameters"); 166 return -1; 167 } 168 return 0; 169 } 170 binding_serial_init(struct mctp * mctp,struct binding * binding,mctp_eid_t eid,int n_params,char * const * params)171 static int binding_serial_init(struct mctp *mctp, struct binding *binding, 172 mctp_eid_t eid, int n_params, 173 char *const *params) 174 { 175 struct mctp_binding_serial *serial; 176 const char *path; 177 int rc; 178 179 if (n_params != 1) { 180 warnx("serial binding requires device param"); 181 return -1; 182 } 183 184 path = params[0]; 185 186 serial = mctp_serial_init(); 187 assert(serial); 188 189 rc = mctp_serial_open_path(serial, path); 190 if (rc) 191 return -1; 192 193 mctp_register_bus(mctp, mctp_binding_serial_core(serial), eid); 194 195 binding->data = serial; 196 197 return 0; 198 } 199 binding_serial_init_pollfd(struct binding * binding,struct pollfd * pollfd)200 static int binding_serial_init_pollfd(struct binding *binding, 201 struct pollfd *pollfd) 202 { 203 return mctp_serial_init_pollfd(binding->data, pollfd); 204 } 205 binding_serial_process(struct binding * binding)206 static int binding_serial_process(struct binding *binding) 207 { 208 return mctp_serial_read(binding->data); 209 } 210 binding_astlpc_init(struct mctp * mctp,struct binding * binding,mctp_eid_t eid,int n_params,char * const * params)211 static int binding_astlpc_init(struct mctp *mctp, struct binding *binding, 212 mctp_eid_t eid, int n_params, 213 char *const *params __attribute__((unused))) 214 { 215 struct mctp_binding_astlpc *astlpc; 216 const char *path; 217 218 if (n_params != 1) { 219 warnx("astlpc binding requires kcs device param"); 220 return -1; 221 } 222 223 path = params[0]; 224 225 astlpc = mctp_astlpc_init_fileio(path); 226 if (!astlpc) { 227 warnx("could not initialise astlpc binding"); 228 return -1; 229 } 230 231 mctp_register_bus(mctp, mctp_binding_astlpc_core(astlpc), eid); 232 233 binding->data = astlpc; 234 return 0; 235 } 236 binding_astlpc_destroy(struct mctp * mctp,struct binding * binding)237 static void binding_astlpc_destroy(struct mctp *mctp, struct binding *binding) 238 { 239 struct mctp_binding_astlpc *astlpc = binding->data; 240 241 mctp_unregister_bus(mctp, mctp_binding_astlpc_core(astlpc)); 242 243 mctp_astlpc_destroy(astlpc); 244 } 245 binding_astlpc_init_pollfd(struct binding * binding,struct pollfd * pollfd)246 static int binding_astlpc_init_pollfd(struct binding *binding, 247 struct pollfd *pollfd) 248 { 249 return mctp_astlpc_init_pollfd(binding->data, pollfd); 250 } 251 binding_astlpc_process(struct binding * binding)252 static int binding_astlpc_process(struct binding *binding) 253 { 254 return mctp_astlpc_poll(binding->data); 255 } 256 257 struct binding bindings[] = { { 258 .name = "null", 259 .init = binding_null_init, 260 }, 261 { 262 .name = "serial", 263 .init = binding_serial_init, 264 .destroy = NULL, 265 .init_pollfd = binding_serial_init_pollfd, 266 .process = binding_serial_process, 267 }, 268 { 269 .name = "astlpc", 270 .init = binding_astlpc_init, 271 .destroy = binding_astlpc_destroy, 272 .init_pollfd = binding_astlpc_init_pollfd, 273 .process = binding_astlpc_process, 274 } }; 275 binding_lookup(const char * name)276 struct binding *binding_lookup(const char *name) 277 { 278 struct binding *binding; 279 unsigned int i; 280 281 for (i = 0; i < ARRAY_SIZE(bindings); i++) { 282 binding = &bindings[i]; 283 284 if (!strcmp(binding->name, name)) 285 return binding; 286 } 287 288 return NULL; 289 } 290 socket_init(struct ctx * ctx)291 static int socket_init(struct ctx *ctx) 292 { 293 struct sockaddr_un addr; 294 int namelen, rc; 295 296 namelen = sizeof(sockname) - 1; 297 addr.sun_family = AF_UNIX; 298 memcpy(addr.sun_path, sockname, namelen); 299 300 ctx->sock = socket(AF_UNIX, SOCK_SEQPACKET, 0); 301 if (ctx->sock < 0) { 302 warn("can't create socket"); 303 return -1; 304 } 305 306 rc = bind(ctx->sock, (struct sockaddr *)&addr, 307 sizeof(addr.sun_family) + namelen); 308 if (rc) { 309 warn("can't bind socket"); 310 goto err_close; 311 } 312 313 rc = listen(ctx->sock, 1); 314 if (rc) { 315 warn("can't listen on socket"); 316 goto err_close; 317 } 318 319 return 0; 320 321 err_close: 322 close(ctx->sock); 323 return -1; 324 } 325 socket_process(struct ctx * ctx)326 static int socket_process(struct ctx *ctx) 327 { 328 struct client *client; 329 int fd; 330 331 fd = accept4(ctx->sock, NULL, 0, SOCK_NONBLOCK); 332 if (fd < 0) 333 return -1; 334 335 ctx->n_clients++; 336 ctx->clients = 337 realloc(ctx->clients, ctx->n_clients * sizeof(struct client)); 338 339 client = &ctx->clients[ctx->n_clients - 1]; 340 memset(client, 0, sizeof(*client)); 341 client->active = true; 342 client->sock = fd; 343 344 return 0; 345 } 346 client_process_recv(struct ctx * ctx,int idx)347 static int client_process_recv(struct ctx *ctx, int idx) 348 { 349 struct client *client = &ctx->clients[idx]; 350 uint8_t eid; 351 ssize_t len; 352 int rc; 353 354 /* are we waiting for a type message? */ 355 if (!client->type) { 356 uint8_t type; 357 rc = read(client->sock, &type, 1); 358 if (rc <= 0) 359 goto out_close; 360 361 if (type == 0) { 362 rc = -1; 363 goto out_close; 364 } 365 if (ctx->verbose) 366 fprintf(stderr, "client[%d] registered for type %u\n", 367 idx, type); 368 client->type = type; 369 return 0; 370 } 371 372 len = recv(client->sock, NULL, 0, MSG_PEEK | MSG_TRUNC); 373 if (len < 0) { 374 if (errno != ECONNRESET) 375 warn("can't receive (peek) from client"); 376 377 rc = -1; 378 goto out_close; 379 } 380 381 if ((size_t)len > ctx->buf_size) { 382 void *tmp; 383 384 tmp = realloc(ctx->buf, len); 385 if (!tmp) { 386 warn("can't allocate for incoming message"); 387 rc = -1; 388 goto out_close; 389 } 390 ctx->buf = tmp; 391 ctx->buf_size = len; 392 } 393 394 rc = recv(client->sock, ctx->buf, ctx->buf_size, 0); 395 if (rc < 0) { 396 if (errno != ECONNRESET) 397 warn("can't receive from client"); 398 rc = -1; 399 goto out_close; 400 } 401 402 if (rc <= 0) { 403 rc = -1; 404 goto out_close; 405 } 406 407 eid = *(uint8_t *)ctx->buf; 408 409 if (ctx->pcap.socket.path) 410 capture_socket(ctx->pcap.socket.dumper, ctx->buf, rc, 411 MCTP_MESSAGE_CAPTURE_OUTGOING, eid); 412 413 if (ctx->verbose) 414 fprintf(stderr, "client[%d] sent message: dest 0x%02x len %d\n", 415 idx, eid, rc - 1); 416 417 if (eid == ctx->local_eid) 418 rx_message(eid, MCTP_MESSAGE_TO_DST, 0, ctx, ctx->buf + 1, 419 rc - 1); 420 else 421 tx_message(ctx, eid, ctx->buf + 1, rc - 1); 422 423 return 0; 424 425 out_close: 426 client->active = false; 427 return rc; 428 } 429 binding_init(struct ctx * ctx,const char * name,int argc,char * const * argv)430 static int binding_init(struct ctx *ctx, const char *name, int argc, 431 char *const *argv) 432 { 433 int rc; 434 435 ctx->binding = binding_lookup(name); 436 if (!ctx->binding) { 437 warnx("no such binding '%s'", name); 438 return -1; 439 } 440 441 rc = ctx->binding->init(ctx->mctp, ctx->binding, ctx->local_eid, argc, 442 argv); 443 return rc; 444 } 445 binding_destroy(struct ctx * ctx)446 static void binding_destroy(struct ctx *ctx) 447 { 448 if (ctx->binding->destroy) 449 ctx->binding->destroy(ctx->mctp, ctx->binding); 450 } 451 452 enum { 453 FD_BINDING = 0, 454 FD_SOCKET, 455 FD_SIGNAL, 456 FD_NR, 457 }; 458 run_daemon(struct ctx * ctx)459 static int run_daemon(struct ctx *ctx) 460 { 461 bool clients_changed = false; 462 sigset_t mask; 463 int rc, i; 464 465 ctx->pollfds = malloc(FD_NR * sizeof(struct pollfd)); 466 467 if (!ctx->binding->init_pollfd) { 468 ctx->pollfds[FD_BINDING].fd = -1; 469 ctx->pollfds[FD_BINDING].events = 0; 470 } 471 472 sigemptyset(&mask); 473 sigaddset(&mask, SIGINT); 474 sigaddset(&mask, SIGTERM); 475 sigaddset(&mask, SIGQUIT); 476 477 if ((rc = sigprocmask(SIG_BLOCK, &mask, NULL)) == -1) { 478 warn("sigprocmask"); 479 return rc; 480 } 481 482 ctx->pollfds[FD_SIGNAL].fd = signalfd(-1, &mask, 0); 483 ctx->pollfds[FD_SIGNAL].events = POLLIN; 484 485 ctx->pollfds[FD_SOCKET].fd = ctx->sock; 486 ctx->pollfds[FD_SOCKET].events = POLLIN; 487 488 mctp_set_rx_all(ctx->mctp, rx_message, ctx); 489 490 for (;;) { 491 if (clients_changed) { 492 int i; 493 494 ctx->pollfds = realloc(ctx->pollfds, 495 (ctx->n_clients + FD_NR) * 496 sizeof(struct pollfd)); 497 498 for (i = 0; i < ctx->n_clients; i++) { 499 ctx->pollfds[FD_NR + i].fd = 500 ctx->clients[i].sock; 501 ctx->pollfds[FD_NR + i].events = POLLIN; 502 } 503 clients_changed = false; 504 } 505 506 if (ctx->binding->init_pollfd) 507 ctx->binding->init_pollfd(ctx->binding, 508 &ctx->pollfds[FD_BINDING]); 509 rc = poll(ctx->pollfds, ctx->n_clients + FD_NR, -1); 510 if (rc < 0) { 511 warn("poll failed"); 512 break; 513 } 514 515 if (!rc) 516 continue; 517 518 if (ctx->pollfds[FD_SIGNAL].revents) { 519 struct signalfd_siginfo si; 520 ssize_t got; 521 522 got = read(ctx->pollfds[FD_SIGNAL].fd, &si, sizeof(si)); 523 if (got == sizeof(si)) { 524 warnx("Received %s, quitting", 525 strsignal(si.ssi_signo)); 526 rc = 0; 527 break; 528 } else { 529 warnx("Unexpected read result for signalfd: %d", 530 rc); 531 warnx("Quitting on the basis that signalfd became ready"); 532 rc = -1; 533 break; 534 } 535 } 536 537 if (ctx->pollfds[FD_BINDING].revents) { 538 rc = 0; 539 if (ctx->binding->process) 540 rc = ctx->binding->process(ctx->binding); 541 if (rc) 542 break; 543 } 544 545 for (i = 0; i < ctx->n_clients; i++) { 546 if (!ctx->pollfds[FD_NR + i].revents) 547 continue; 548 549 rc = client_process_recv(ctx, i); 550 if (rc) 551 clients_changed = true; 552 } 553 554 if (ctx->pollfds[FD_SOCKET].revents) { 555 rc = socket_process(ctx); 556 if (rc) 557 break; 558 clients_changed = true; 559 } 560 561 if (clients_changed) 562 client_remove_inactive(ctx); 563 } 564 565 free(ctx->pollfds); 566 567 return rc; 568 } 569 570 static const struct option options[] = { 571 { "capture-binding", required_argument, 0, 'b' }, 572 { "capture-socket", required_argument, 0, 's' }, 573 { "binding-linktype", required_argument, 0, 'B' }, 574 { "socket-linktype", required_argument, 0, 'S' }, 575 { "verbose", no_argument, 0, 'v' }, 576 { "eid", required_argument, 0, 'e' }, 577 { 0 }, 578 }; 579 usage(const char * progname)580 static void usage(const char *progname) 581 { 582 unsigned int i; 583 584 fprintf(stderr, "usage: %s <binding> [params]\n", progname); 585 fprintf(stderr, "Available bindings:\n"); 586 for (i = 0; i < ARRAY_SIZE(bindings); i++) 587 fprintf(stderr, " %s\n", bindings[i].name); 588 } 589 main(int argc,char * const * argv)590 int main(int argc, char *const *argv) 591 { 592 struct ctx *ctx, _ctx; 593 int rc; 594 595 ctx = &_ctx; 596 ctx->clients = NULL; 597 ctx->n_clients = 0; 598 ctx->local_eid = local_eid_default; 599 ctx->verbose = false; 600 ctx->pcap.binding.path = NULL; 601 ctx->pcap.socket.path = NULL; 602 603 for (;;) { 604 rc = getopt_long(argc, argv, "b:es::v", options, NULL); 605 if (rc == -1) 606 break; 607 switch (rc) { 608 case 'b': 609 ctx->pcap.binding.path = optarg; 610 break; 611 case 's': 612 ctx->pcap.socket.path = optarg; 613 break; 614 case 'B': 615 fprintf(stderr, 616 "binding-linktype argument is deprecated\n"); 617 break; 618 case 'S': 619 fprintf(stderr, 620 "socket-linktype argument is deprecated\n"); 621 break; 622 case 'v': 623 ctx->verbose = true; 624 break; 625 case 'e': 626 ctx->local_eid = atoi(optarg); 627 break; 628 default: 629 fprintf(stderr, "Invalid argument\n"); 630 return EXIT_FAILURE; 631 } 632 } 633 634 if (optind >= argc) { 635 fprintf(stderr, "missing binding argument\n"); 636 usage(argv[0]); 637 return EXIT_FAILURE; 638 } 639 640 /* setup initial buffer */ 641 ctx->buf_size = 4096; 642 ctx->buf = malloc(ctx->buf_size); 643 644 mctp_set_log_stdio(ctx->verbose ? MCTP_LOG_DEBUG : MCTP_LOG_NOTICE); 645 646 ctx->mctp = mctp_init(); 647 assert(ctx->mctp); 648 649 if (ctx->pcap.binding.path || ctx->pcap.socket.path) { 650 if (capture_init()) { 651 rc = EXIT_FAILURE; 652 goto cleanup_mctp; 653 } 654 } 655 656 if (ctx->pcap.binding.path) { 657 rc = capture_prepare(&ctx->pcap.binding); 658 if (rc == -1) { 659 fprintf(stderr, "Failed to initialise capture: %d\n", 660 rc); 661 rc = EXIT_FAILURE; 662 goto cleanup_mctp; 663 } 664 665 mctp_set_capture_handler(ctx->mctp, capture_binding, 666 ctx->pcap.binding.dumper); 667 } 668 669 if (ctx->pcap.socket.path) { 670 rc = capture_prepare(&ctx->pcap.socket); 671 if (rc == -1) { 672 fprintf(stderr, "Failed to initialise capture: %d\n", 673 rc); 674 rc = EXIT_FAILURE; 675 goto cleanup_pcap_binding; 676 } 677 } 678 679 rc = binding_init(ctx, argv[optind], argc - optind - 1, 680 argv + optind + 1); 681 if (rc) { 682 fprintf(stderr, "Failed to initialise binding: %d\n", rc); 683 rc = EXIT_FAILURE; 684 goto cleanup_pcap_socket; 685 } 686 687 rc = sd_listen_fds(true); 688 if (rc <= 0) { 689 rc = socket_init(ctx); 690 if (rc) { 691 fprintf(stderr, "Failed to initialse socket: %d\n", rc); 692 goto cleanup_binding; 693 } 694 } else { 695 ctx->sock = SD_LISTEN_FDS_START; 696 } 697 698 rc = run_daemon(ctx); 699 700 cleanup_binding: 701 binding_destroy(ctx); 702 703 cleanup_pcap_socket: 704 if (ctx->pcap.socket.path) 705 capture_close(&ctx->pcap.socket); 706 707 cleanup_pcap_binding: 708 if (ctx->pcap.binding.path) 709 capture_close(&ctx->pcap.binding); 710 711 rc = rc ? EXIT_FAILURE : EXIT_SUCCESS; 712 cleanup_mctp: 713 714 return rc; 715 } 716