13d36ee2eSJeremy Kerr /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ 23d36ee2eSJeremy Kerr 38e31cfd1SJeremy Kerr #define _GNU_SOURCE 48e31cfd1SJeremy Kerr 58e31cfd1SJeremy Kerr #include <assert.h> 68e31cfd1SJeremy Kerr #include <err.h> 78e31cfd1SJeremy Kerr #include <getopt.h> 88e31cfd1SJeremy Kerr #include <poll.h> 98e31cfd1SJeremy Kerr #include <stdio.h> 108e31cfd1SJeremy Kerr #include <stdlib.h> 118e31cfd1SJeremy Kerr #include <string.h> 128e31cfd1SJeremy Kerr #include <unistd.h> 138e31cfd1SJeremy Kerr 148e31cfd1SJeremy Kerr #include <sys/socket.h> 158e31cfd1SJeremy Kerr #include <sys/un.h> 168e31cfd1SJeremy Kerr 178e31cfd1SJeremy Kerr #include "libmctp.h" 188e31cfd1SJeremy Kerr #include "libmctp-serial.h" 198e31cfd1SJeremy Kerr #include "libmctp-astlpc.h" 208e31cfd1SJeremy Kerr 218e31cfd1SJeremy Kerr #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 228e31cfd1SJeremy Kerr 238e31cfd1SJeremy Kerr static const mctp_eid_t local_eid_default = 8; 248e31cfd1SJeremy Kerr static char sockname[] = "\0mctp-mux"; 258e31cfd1SJeremy Kerr 268e31cfd1SJeremy Kerr struct binding { 278e31cfd1SJeremy Kerr const char *name; 288e31cfd1SJeremy Kerr int (*init)(struct mctp *mctp, struct binding *binding, 298e31cfd1SJeremy Kerr mctp_eid_t eid, int n_params, 308e31cfd1SJeremy Kerr char * const * params); 318e31cfd1SJeremy Kerr int (*get_fd)(struct binding *binding); 328e31cfd1SJeremy Kerr int (*process)(struct binding *binding); 338e31cfd1SJeremy Kerr void *data; 348e31cfd1SJeremy Kerr }; 358e31cfd1SJeremy Kerr 368e31cfd1SJeremy Kerr struct client { 378e31cfd1SJeremy Kerr bool active; 388e31cfd1SJeremy Kerr int sock; 398e31cfd1SJeremy Kerr uint8_t type; 408e31cfd1SJeremy Kerr }; 418e31cfd1SJeremy Kerr 428e31cfd1SJeremy Kerr struct ctx { 438e31cfd1SJeremy Kerr struct mctp *mctp; 448e31cfd1SJeremy Kerr struct binding *binding; 458e31cfd1SJeremy Kerr bool verbose; 468e31cfd1SJeremy Kerr int local_eid; 478e31cfd1SJeremy Kerr 488e31cfd1SJeremy Kerr int sock; 498e31cfd1SJeremy Kerr struct pollfd *pollfds; 508e31cfd1SJeremy Kerr 518e31cfd1SJeremy Kerr struct client *clients; 528e31cfd1SJeremy Kerr int n_clients; 538e31cfd1SJeremy Kerr }; 548e31cfd1SJeremy Kerr 558e31cfd1SJeremy Kerr static void tx_message(struct ctx *ctx, mctp_eid_t eid, void *msg, size_t len) 568e31cfd1SJeremy Kerr { 578e31cfd1SJeremy Kerr mctp_message_tx(ctx->mctp, eid, msg, len); 588e31cfd1SJeremy Kerr } 598e31cfd1SJeremy Kerr 608e31cfd1SJeremy Kerr static void client_remove_inactive(struct ctx *ctx) 618e31cfd1SJeremy Kerr { 628e31cfd1SJeremy Kerr int i; 638e31cfd1SJeremy Kerr 648e31cfd1SJeremy Kerr for (i = 0; i < ctx->n_clients; i++) { 658e31cfd1SJeremy Kerr struct client *client = &ctx->clients[i]; 668e31cfd1SJeremy Kerr if (client->active) 678e31cfd1SJeremy Kerr continue; 688e31cfd1SJeremy Kerr close(client->sock); 698e31cfd1SJeremy Kerr 708e31cfd1SJeremy Kerr ctx->n_clients--; 718e31cfd1SJeremy Kerr memmove(&ctx->clients[i], &ctx->clients[i+1], 728e31cfd1SJeremy Kerr (ctx->n_clients - i) * sizeof(*ctx->clients)); 738e31cfd1SJeremy Kerr ctx->clients = realloc(ctx->clients, 748e31cfd1SJeremy Kerr ctx->n_clients * sizeof(*ctx->clients)); 758e31cfd1SJeremy Kerr } 768e31cfd1SJeremy Kerr } 778e31cfd1SJeremy Kerr 788e31cfd1SJeremy Kerr static void rx_message(uint8_t eid, void *data, void *msg, size_t len) 798e31cfd1SJeremy Kerr { 808e31cfd1SJeremy Kerr struct ctx *ctx = data; 818e31cfd1SJeremy Kerr struct iovec iov[2]; 828e31cfd1SJeremy Kerr struct msghdr msghdr; 838e31cfd1SJeremy Kerr bool removed; 848e31cfd1SJeremy Kerr uint8_t type; 858e31cfd1SJeremy Kerr int i, rc; 868e31cfd1SJeremy Kerr 878e31cfd1SJeremy Kerr if (len < 2) 888e31cfd1SJeremy Kerr return; 898e31cfd1SJeremy Kerr 908e31cfd1SJeremy Kerr type = *(uint8_t *)msg; 918e31cfd1SJeremy Kerr 928e31cfd1SJeremy Kerr if (ctx->verbose) 938e31cfd1SJeremy Kerr fprintf(stderr, "MCTP message received: len %zd, type %d\n", 948e31cfd1SJeremy Kerr len, type); 958e31cfd1SJeremy Kerr 968e31cfd1SJeremy Kerr memset(&msghdr, 0, sizeof(msghdr)); 978e31cfd1SJeremy Kerr msghdr.msg_iov = iov; 988e31cfd1SJeremy Kerr msghdr.msg_iovlen = 2; 998e31cfd1SJeremy Kerr iov[0].iov_base = &eid; 1008e31cfd1SJeremy Kerr iov[0].iov_len = 1; 1018e31cfd1SJeremy Kerr iov[1].iov_base = msg; 1028e31cfd1SJeremy Kerr iov[1].iov_len = len; 1038e31cfd1SJeremy Kerr 1048e31cfd1SJeremy Kerr for (i = 0; i < ctx->n_clients; i++) { 1058e31cfd1SJeremy Kerr struct client *client = &ctx->clients[i]; 1068e31cfd1SJeremy Kerr 1078e31cfd1SJeremy Kerr if (client->type != type) 1088e31cfd1SJeremy Kerr continue; 1098e31cfd1SJeremy Kerr 1108e31cfd1SJeremy Kerr if (ctx->verbose) 1118e31cfd1SJeremy Kerr fprintf(stderr, " forwarding to client %d\n", i); 1128e31cfd1SJeremy Kerr 1138e31cfd1SJeremy Kerr rc = sendmsg(client->sock, &msghdr, 0); 1148e31cfd1SJeremy Kerr if (rc != (ssize_t)(len + 1)) { 1158e31cfd1SJeremy Kerr client->active = false; 1168e31cfd1SJeremy Kerr removed = true; 1178e31cfd1SJeremy Kerr } 1188e31cfd1SJeremy Kerr } 1198e31cfd1SJeremy Kerr 1208e31cfd1SJeremy Kerr if (removed) 1218e31cfd1SJeremy Kerr client_remove_inactive(ctx); 1228e31cfd1SJeremy Kerr 1238e31cfd1SJeremy Kerr } 1248e31cfd1SJeremy Kerr 1258e31cfd1SJeremy Kerr static int binding_serial_init(struct mctp *mctp, struct binding *binding, 1268e31cfd1SJeremy Kerr mctp_eid_t eid, int n_params, char * const *params) 1278e31cfd1SJeremy Kerr { 1288e31cfd1SJeremy Kerr struct mctp_binding_serial *serial; 1298e31cfd1SJeremy Kerr const char *path; 1308e31cfd1SJeremy Kerr int rc; 1318e31cfd1SJeremy Kerr 1328e31cfd1SJeremy Kerr if (n_params != 1) { 1338e31cfd1SJeremy Kerr warnx("serial binding requires device param"); 1348e31cfd1SJeremy Kerr return -1; 1358e31cfd1SJeremy Kerr } 1368e31cfd1SJeremy Kerr 1378e31cfd1SJeremy Kerr path = params[0]; 1388e31cfd1SJeremy Kerr 1398e31cfd1SJeremy Kerr serial = mctp_serial_init(); 1408e31cfd1SJeremy Kerr assert(serial); 1418e31cfd1SJeremy Kerr 1428e31cfd1SJeremy Kerr rc = mctp_serial_open_path(serial, path); 1438e31cfd1SJeremy Kerr if (rc) 1448e31cfd1SJeremy Kerr return -1; 1458e31cfd1SJeremy Kerr 1468e31cfd1SJeremy Kerr mctp_serial_register_bus(serial, mctp, eid); 1478e31cfd1SJeremy Kerr 1488e31cfd1SJeremy Kerr binding->data = serial; 1498e31cfd1SJeremy Kerr 1508e31cfd1SJeremy Kerr return 0; 1518e31cfd1SJeremy Kerr } 1528e31cfd1SJeremy Kerr 1538e31cfd1SJeremy Kerr static int binding_serial_get_fd(struct binding *binding) 1548e31cfd1SJeremy Kerr { 1558e31cfd1SJeremy Kerr return mctp_serial_get_fd(binding->data); 1568e31cfd1SJeremy Kerr } 1578e31cfd1SJeremy Kerr 1588e31cfd1SJeremy Kerr static int binding_serial_process(struct binding *binding) 1598e31cfd1SJeremy Kerr { 1608e31cfd1SJeremy Kerr return mctp_serial_read(binding->data); 1618e31cfd1SJeremy Kerr } 1628e31cfd1SJeremy Kerr 1638e31cfd1SJeremy Kerr static int binding_astlpc_init(struct mctp *mctp, struct binding *binding, 1648e31cfd1SJeremy Kerr mctp_eid_t eid, int n_params, 1658e31cfd1SJeremy Kerr char * const *params __attribute__((unused))) 1668e31cfd1SJeremy Kerr { 1678e31cfd1SJeremy Kerr struct mctp_binding_astlpc *astlpc; 1688e31cfd1SJeremy Kerr 1698e31cfd1SJeremy Kerr if (n_params) { 1708e31cfd1SJeremy Kerr warnx("astlpc binding does not accept parameters"); 1718e31cfd1SJeremy Kerr return -1; 1728e31cfd1SJeremy Kerr } 1738e31cfd1SJeremy Kerr 1748e31cfd1SJeremy Kerr astlpc = mctp_astlpc_init(); 1758e31cfd1SJeremy Kerr if (!astlpc) { 1768e31cfd1SJeremy Kerr warnx("could not initialise astlpc binding"); 1778e31cfd1SJeremy Kerr return -1; 1788e31cfd1SJeremy Kerr } 1798e31cfd1SJeremy Kerr 1808e31cfd1SJeremy Kerr mctp_astlpc_register_bus(astlpc, mctp, eid); 1818e31cfd1SJeremy Kerr binding->data = astlpc; 1828e31cfd1SJeremy Kerr return 0; 1838e31cfd1SJeremy Kerr } 1848e31cfd1SJeremy Kerr 1858e31cfd1SJeremy Kerr static int binding_astlpc_get_fd(struct binding *binding) 1868e31cfd1SJeremy Kerr { 1878e31cfd1SJeremy Kerr return mctp_astlpc_get_fd(binding->data); 1888e31cfd1SJeremy Kerr } 1898e31cfd1SJeremy Kerr 1908e31cfd1SJeremy Kerr static int binding_astlpc_process(struct binding *binding) 1918e31cfd1SJeremy Kerr { 1928e31cfd1SJeremy Kerr return mctp_astlpc_poll(binding->data); 1938e31cfd1SJeremy Kerr } 1948e31cfd1SJeremy Kerr 1958e31cfd1SJeremy Kerr struct binding bindings[] = { 1968e31cfd1SJeremy Kerr { 1978e31cfd1SJeremy Kerr .name = "serial", 1988e31cfd1SJeremy Kerr .init = binding_serial_init, 1998e31cfd1SJeremy Kerr .get_fd = binding_serial_get_fd, 2008e31cfd1SJeremy Kerr .process = binding_serial_process, 2018e31cfd1SJeremy Kerr }, 2028e31cfd1SJeremy Kerr { 2038e31cfd1SJeremy Kerr .name = "astlpc", 2048e31cfd1SJeremy Kerr .init = binding_astlpc_init, 2058e31cfd1SJeremy Kerr .get_fd = binding_astlpc_get_fd, 2068e31cfd1SJeremy Kerr .process = binding_astlpc_process, 2078e31cfd1SJeremy Kerr } 2088e31cfd1SJeremy Kerr }; 2098e31cfd1SJeremy Kerr 2108e31cfd1SJeremy Kerr struct binding *binding_lookup(const char *name) 2118e31cfd1SJeremy Kerr { 2128e31cfd1SJeremy Kerr struct binding *binding; 2138e31cfd1SJeremy Kerr unsigned int i; 2148e31cfd1SJeremy Kerr 2158e31cfd1SJeremy Kerr for (i = 0; i < ARRAY_SIZE(bindings); i++) { 2168e31cfd1SJeremy Kerr binding = &bindings[i]; 2178e31cfd1SJeremy Kerr 2188e31cfd1SJeremy Kerr if (!strcmp(binding->name, name)) 2198e31cfd1SJeremy Kerr return binding; 2208e31cfd1SJeremy Kerr } 2218e31cfd1SJeremy Kerr 2228e31cfd1SJeremy Kerr return NULL; 2238e31cfd1SJeremy Kerr } 2248e31cfd1SJeremy Kerr 2258e31cfd1SJeremy Kerr static int socket_init(struct ctx *ctx) 2268e31cfd1SJeremy Kerr { 2278e31cfd1SJeremy Kerr struct sockaddr_un addr; 2288e31cfd1SJeremy Kerr int namelen, rc; 2298e31cfd1SJeremy Kerr 2308e31cfd1SJeremy Kerr namelen = sizeof(sockname) - 1; 2318e31cfd1SJeremy Kerr addr.sun_family = AF_UNIX; 2328e31cfd1SJeremy Kerr memcpy(addr.sun_path, sockname, namelen); 2338e31cfd1SJeremy Kerr 2348e31cfd1SJeremy Kerr ctx->sock = socket(AF_UNIX, SOCK_SEQPACKET, 0); 2358e31cfd1SJeremy Kerr if (ctx->sock < 0) { 2368e31cfd1SJeremy Kerr warn("can't create socket"); 2378e31cfd1SJeremy Kerr return -1; 2388e31cfd1SJeremy Kerr } 2398e31cfd1SJeremy Kerr 2408e31cfd1SJeremy Kerr rc = bind(ctx->sock, (struct sockaddr *)&addr, 2418e31cfd1SJeremy Kerr sizeof(addr.sun_family) + namelen); 2428e31cfd1SJeremy Kerr if (rc) { 2438e31cfd1SJeremy Kerr warn("can't bind socket"); 2448e31cfd1SJeremy Kerr goto err_close; 2458e31cfd1SJeremy Kerr } 2468e31cfd1SJeremy Kerr 2478e31cfd1SJeremy Kerr rc = listen(ctx->sock, 1); 2488e31cfd1SJeremy Kerr if (rc) { 2498e31cfd1SJeremy Kerr warn("can't listen on socket"); 2508e31cfd1SJeremy Kerr goto err_close; 2518e31cfd1SJeremy Kerr } 2528e31cfd1SJeremy Kerr 2538e31cfd1SJeremy Kerr return 0; 2548e31cfd1SJeremy Kerr 2558e31cfd1SJeremy Kerr err_close: 2568e31cfd1SJeremy Kerr close(ctx->sock); 2578e31cfd1SJeremy Kerr return -1; 2588e31cfd1SJeremy Kerr } 2598e31cfd1SJeremy Kerr 2608e31cfd1SJeremy Kerr static int socket_process(struct ctx *ctx) 2618e31cfd1SJeremy Kerr { 2628e31cfd1SJeremy Kerr struct client *client; 2638e31cfd1SJeremy Kerr int fd; 2648e31cfd1SJeremy Kerr 2658e31cfd1SJeremy Kerr fd = accept4(ctx->sock, NULL, 0, SOCK_NONBLOCK); 2668e31cfd1SJeremy Kerr if (fd < 0) 2678e31cfd1SJeremy Kerr return -1; 2688e31cfd1SJeremy Kerr 2698e31cfd1SJeremy Kerr ctx->n_clients++; 2708e31cfd1SJeremy Kerr ctx->clients = realloc(ctx->clients, 2718e31cfd1SJeremy Kerr ctx->n_clients * sizeof(struct client)); 2728e31cfd1SJeremy Kerr 2738e31cfd1SJeremy Kerr client = &ctx->clients[ctx->n_clients-1]; 2748e31cfd1SJeremy Kerr memset(client, 0, sizeof(client)); 2758e31cfd1SJeremy Kerr client->active = true; 2768e31cfd1SJeremy Kerr client->sock = fd; 2778e31cfd1SJeremy Kerr 2788e31cfd1SJeremy Kerr return 0; 2798e31cfd1SJeremy Kerr } 2808e31cfd1SJeremy Kerr 2818e31cfd1SJeremy Kerr static int client_process_recv(struct ctx *ctx, int idx) 2828e31cfd1SJeremy Kerr { 2838e31cfd1SJeremy Kerr struct client *client = &ctx->clients[idx]; 2848e31cfd1SJeremy Kerr uint8_t buf[4096]; 2858e31cfd1SJeremy Kerr int rc; 2868e31cfd1SJeremy Kerr 2878e31cfd1SJeremy Kerr /* are we waiting for a type message? */ 2888e31cfd1SJeremy Kerr if (!client->type) { 2898e31cfd1SJeremy Kerr uint8_t type; 2908e31cfd1SJeremy Kerr rc = read(client->sock, &type, 1); 2918e31cfd1SJeremy Kerr if (rc <= 0) 2928e31cfd1SJeremy Kerr goto out_close; 2938e31cfd1SJeremy Kerr 2948e31cfd1SJeremy Kerr if (type == 0) { 2958e31cfd1SJeremy Kerr rc = -1; 2968e31cfd1SJeremy Kerr goto out_close; 2978e31cfd1SJeremy Kerr } 2988e31cfd1SJeremy Kerr if (ctx->verbose) 2998e31cfd1SJeremy Kerr fprintf(stderr, "client[%d] registered for type %u\n", 3008e31cfd1SJeremy Kerr idx, type); 3018e31cfd1SJeremy Kerr client->type = type; 3028e31cfd1SJeremy Kerr return 0; 3038e31cfd1SJeremy Kerr } 3048e31cfd1SJeremy Kerr 3058e31cfd1SJeremy Kerr /* todo: size detection through MSG_TRUNC or MSG_PEEK */ 3068e31cfd1SJeremy Kerr rc = recv(client->sock, buf, sizeof(buf), 0); 3078e31cfd1SJeremy Kerr if (rc < 0) { 3088e31cfd1SJeremy Kerr warn("can't receive from client"); 3098e31cfd1SJeremy Kerr goto out_close; 3108e31cfd1SJeremy Kerr } 3118e31cfd1SJeremy Kerr 3128e31cfd1SJeremy Kerr if (rc == 0) { 3138e31cfd1SJeremy Kerr rc = -1; 3148e31cfd1SJeremy Kerr goto out_close; 3158e31cfd1SJeremy Kerr } 3168e31cfd1SJeremy Kerr 3178e31cfd1SJeremy Kerr if (rc > 0) { 3188e31cfd1SJeremy Kerr uint8_t eid = buf[0]; 3198e31cfd1SJeremy Kerr if (ctx->verbose) 3208e31cfd1SJeremy Kerr fprintf(stderr, 3218e31cfd1SJeremy Kerr "client[%d] sent message: dest 0x%02x len %d\n", 3228e31cfd1SJeremy Kerr idx, eid, rc - 1); 3238e31cfd1SJeremy Kerr 3248e31cfd1SJeremy Kerr tx_message(ctx, eid, buf + 1, rc - 1); 3258e31cfd1SJeremy Kerr } 3268e31cfd1SJeremy Kerr 3278e31cfd1SJeremy Kerr return 0; 3288e31cfd1SJeremy Kerr 3298e31cfd1SJeremy Kerr out_close: 3308e31cfd1SJeremy Kerr client->active = false; 3318e31cfd1SJeremy Kerr return rc; 3328e31cfd1SJeremy Kerr } 3338e31cfd1SJeremy Kerr 3348e31cfd1SJeremy Kerr static int binding_init(struct ctx *ctx, const char *name, 3358e31cfd1SJeremy Kerr int argc, char * const *argv) 3368e31cfd1SJeremy Kerr { 3378e31cfd1SJeremy Kerr int rc; 3388e31cfd1SJeremy Kerr 3398e31cfd1SJeremy Kerr ctx->binding = binding_lookup(name); 3408e31cfd1SJeremy Kerr if (!ctx->binding) { 3418e31cfd1SJeremy Kerr warnx("no such binding '%s'", name); 3428e31cfd1SJeremy Kerr return -1; 3438e31cfd1SJeremy Kerr } 3448e31cfd1SJeremy Kerr 3458e31cfd1SJeremy Kerr rc = ctx->binding->init(ctx->mctp, ctx->binding, ctx->local_eid, 3468e31cfd1SJeremy Kerr argc, argv); 3478e31cfd1SJeremy Kerr return rc; 3488e31cfd1SJeremy Kerr } 3498e31cfd1SJeremy Kerr 3508e31cfd1SJeremy Kerr enum { 3518e31cfd1SJeremy Kerr FD_BINDING = 0, 3528e31cfd1SJeremy Kerr FD_SOCKET, 3538e31cfd1SJeremy Kerr FD_NR, 3548e31cfd1SJeremy Kerr }; 3558e31cfd1SJeremy Kerr 3568e31cfd1SJeremy Kerr static int run_daemon(struct ctx *ctx) 3578e31cfd1SJeremy Kerr { 3588e31cfd1SJeremy Kerr bool clients_changed = false; 3598e31cfd1SJeremy Kerr int rc, i; 3608e31cfd1SJeremy Kerr 3618e31cfd1SJeremy Kerr ctx->pollfds = malloc(FD_NR * sizeof(struct pollfd)); 3628e31cfd1SJeremy Kerr 3638e31cfd1SJeremy Kerr ctx->pollfds[FD_BINDING].fd = 3648e31cfd1SJeremy Kerr ctx->binding->get_fd(ctx->binding); 3658e31cfd1SJeremy Kerr ctx->pollfds[FD_BINDING].events = POLLIN; 3668e31cfd1SJeremy Kerr 3678e31cfd1SJeremy Kerr ctx->pollfds[FD_SOCKET].fd = ctx->sock; 3688e31cfd1SJeremy Kerr ctx->pollfds[FD_SOCKET].events = POLLIN; 3698e31cfd1SJeremy Kerr 3708e31cfd1SJeremy Kerr mctp_set_rx_all(ctx->mctp, rx_message, ctx); 3718e31cfd1SJeremy Kerr 3728e31cfd1SJeremy Kerr for (;;) { 3738e31cfd1SJeremy Kerr if (clients_changed) { 3748e31cfd1SJeremy Kerr int i; 3758e31cfd1SJeremy Kerr 3768e31cfd1SJeremy Kerr ctx->pollfds = realloc(ctx->pollfds, 3778e31cfd1SJeremy Kerr (ctx->n_clients + FD_NR) * 3788e31cfd1SJeremy Kerr sizeof(struct pollfd)); 3798e31cfd1SJeremy Kerr 3808e31cfd1SJeremy Kerr for (i = 0; i < ctx->n_clients; i++) { 3818e31cfd1SJeremy Kerr ctx->pollfds[FD_NR+i].fd = 3828e31cfd1SJeremy Kerr ctx->clients[i].sock; 3838e31cfd1SJeremy Kerr ctx->pollfds[FD_NR+i].events = POLLIN; 3848e31cfd1SJeremy Kerr } 3858e31cfd1SJeremy Kerr clients_changed = false; 3868e31cfd1SJeremy Kerr } 3878e31cfd1SJeremy Kerr 3888e31cfd1SJeremy Kerr rc = poll(ctx->pollfds, ctx->n_clients + FD_NR, -1); 3898e31cfd1SJeremy Kerr if (rc < 0) { 3908e31cfd1SJeremy Kerr warn("poll failed"); 3918e31cfd1SJeremy Kerr break; 3928e31cfd1SJeremy Kerr } 3938e31cfd1SJeremy Kerr 3948e31cfd1SJeremy Kerr if (!rc) 3958e31cfd1SJeremy Kerr continue; 3968e31cfd1SJeremy Kerr 3978e31cfd1SJeremy Kerr if (ctx->pollfds[FD_BINDING].revents) { 3988e31cfd1SJeremy Kerr rc = ctx->binding->process(ctx->binding); 3998e31cfd1SJeremy Kerr if (rc) 4008e31cfd1SJeremy Kerr break; 4018e31cfd1SJeremy Kerr } 4028e31cfd1SJeremy Kerr 4038e31cfd1SJeremy Kerr for (i = 0; i < ctx->n_clients; i++) { 4048e31cfd1SJeremy Kerr if (!ctx->pollfds[FD_NR+i].revents) 4058e31cfd1SJeremy Kerr continue; 4068e31cfd1SJeremy Kerr 4078e31cfd1SJeremy Kerr rc = client_process_recv(ctx, i); 4088e31cfd1SJeremy Kerr if (rc) 4098e31cfd1SJeremy Kerr clients_changed = true; 4108e31cfd1SJeremy Kerr } 4118e31cfd1SJeremy Kerr 4128e31cfd1SJeremy Kerr if (ctx->pollfds[FD_SOCKET].revents) { 4138e31cfd1SJeremy Kerr rc = socket_process(ctx); 4148e31cfd1SJeremy Kerr if (rc) 4158e31cfd1SJeremy Kerr break; 4168e31cfd1SJeremy Kerr clients_changed = true; 4178e31cfd1SJeremy Kerr } 4188e31cfd1SJeremy Kerr 4198e31cfd1SJeremy Kerr if (clients_changed) 4208e31cfd1SJeremy Kerr client_remove_inactive(ctx); 4218e31cfd1SJeremy Kerr 4228e31cfd1SJeremy Kerr } 4238e31cfd1SJeremy Kerr 4248e31cfd1SJeremy Kerr 4258e31cfd1SJeremy Kerr free(ctx->pollfds); 4268e31cfd1SJeremy Kerr 4278e31cfd1SJeremy Kerr return rc; 4288e31cfd1SJeremy Kerr } 4298e31cfd1SJeremy Kerr 4308e31cfd1SJeremy Kerr static const struct option options[] = { 4318e31cfd1SJeremy Kerr { "verbose", no_argument, 0, 'v' }, 4328e31cfd1SJeremy Kerr { "eid", required_argument, 0, 'e' }, 4338e31cfd1SJeremy Kerr { 0 }, 4348e31cfd1SJeremy Kerr }; 4358e31cfd1SJeremy Kerr 4368e31cfd1SJeremy Kerr static void usage(const char *progname) 4378e31cfd1SJeremy Kerr { 4388e31cfd1SJeremy Kerr unsigned int i; 4398e31cfd1SJeremy Kerr 4408e31cfd1SJeremy Kerr fprintf(stderr, "usage: %s <binding> [params]\n", progname); 4418e31cfd1SJeremy Kerr fprintf(stderr, "Available bindings:\n"); 4428e31cfd1SJeremy Kerr for (i = 0; i < ARRAY_SIZE(bindings); i++) 4438e31cfd1SJeremy Kerr fprintf(stderr, " %s\n", bindings[i].name); 4448e31cfd1SJeremy Kerr } 4458e31cfd1SJeremy Kerr 4468e31cfd1SJeremy Kerr int main(int argc, char * const *argv) 4478e31cfd1SJeremy Kerr { 4488e31cfd1SJeremy Kerr struct ctx *ctx, _ctx; 4498e31cfd1SJeremy Kerr int rc; 4508e31cfd1SJeremy Kerr 4518e31cfd1SJeremy Kerr ctx = &_ctx; 4528e31cfd1SJeremy Kerr ctx->clients = NULL; 4538e31cfd1SJeremy Kerr ctx->n_clients = 0; 4548e31cfd1SJeremy Kerr ctx->local_eid = local_eid_default; 4558e31cfd1SJeremy Kerr 4568e31cfd1SJeremy Kerr for (;;) { 4578e31cfd1SJeremy Kerr rc = getopt_long(argc, argv, "e:v", options, NULL); 4588e31cfd1SJeremy Kerr if (rc == -1) 4598e31cfd1SJeremy Kerr break; 4608e31cfd1SJeremy Kerr switch (rc) { 4618e31cfd1SJeremy Kerr case 'v': 4628e31cfd1SJeremy Kerr ctx->verbose = true; 4638e31cfd1SJeremy Kerr break; 4648e31cfd1SJeremy Kerr case 'e': 4658e31cfd1SJeremy Kerr ctx->local_eid = atoi(optarg); 4668e31cfd1SJeremy Kerr break; 4678e31cfd1SJeremy Kerr default: 4688e31cfd1SJeremy Kerr fprintf(stderr, "Invalid argument\n"); 4698e31cfd1SJeremy Kerr return EXIT_FAILURE; 4708e31cfd1SJeremy Kerr } 4718e31cfd1SJeremy Kerr } 4728e31cfd1SJeremy Kerr 4738e31cfd1SJeremy Kerr if (optind >= argc) { 4748e31cfd1SJeremy Kerr fprintf(stderr, "missing binding argument\n"); 4758e31cfd1SJeremy Kerr usage(argv[0]); 4768e31cfd1SJeremy Kerr return EXIT_FAILURE; 4778e31cfd1SJeremy Kerr } 4788e31cfd1SJeremy Kerr 479*0b278a63SJeremy Kerr mctp_set_log_stdio(ctx->verbose ? MCTP_LOG_DEBUG : MCTP_LOG_WARNING); 480*0b278a63SJeremy Kerr 4818e31cfd1SJeremy Kerr ctx->mctp = mctp_init(); 4828e31cfd1SJeremy Kerr assert(ctx->mctp); 4838e31cfd1SJeremy Kerr 4848e31cfd1SJeremy Kerr rc = binding_init(ctx, argv[optind], argc - optind - 1, argv + optind + 1); 4858e31cfd1SJeremy Kerr if (rc) 4868e31cfd1SJeremy Kerr return EXIT_FAILURE; 4878e31cfd1SJeremy Kerr 4888e31cfd1SJeremy Kerr rc = socket_init(ctx); 4898e31cfd1SJeremy Kerr if (rc) 4908e31cfd1SJeremy Kerr return EXIT_FAILURE; 4918e31cfd1SJeremy Kerr 4928e31cfd1SJeremy Kerr rc = run_daemon(ctx); 4938e31cfd1SJeremy Kerr 4948e31cfd1SJeremy Kerr return rc ? EXIT_FAILURE : EXIT_SUCCESS; 4958e31cfd1SJeremy Kerr 4968e31cfd1SJeremy Kerr } 497