void do_read_hostlist(int fd, int timeout) { host_state_t hinfo; fd_set rfds; struct timeval tv; int ret; do { FD_ZERO(&rfds); FD_SET(fd, &rfds); tv.tv_sec = timeout; tv.tv_usec = 0; ret = _select_retry(fd+1, &rfds, NULL, NULL, &tv); if (ret == 0) { printf("Timed out!\n"); break; } ret = _read_retry(fd, &hinfo, sizeof(hinfo), &tv); if (ret < sizeof(hinfo)) { printf("Bad read!\n"); break; } if (strlen((char *)hinfo.uuid) == 0 && strlen((char *)hinfo.domain) == 0) break; printf("%-32s %s %s\n", hinfo.domain, hinfo.uuid, (hinfo.state == 1) ? "on" : "off"); } while (1); }
int wait_for(int fd, const char *pattern, size_t size, struct timeval *tout) { char *pos = (char *)pattern; char c; int n; struct timeval tv; size_t remain = size; if (tout) { memcpy(&tv, tout, sizeof(tv)); tout = &tv; } while (remain) { n = _read_retry(fd, &c, 1, &tv); if (n < 1) return -1; if (c == *pos) { ++pos; --remain; } else { pos = (char *)pattern; remain = size; } } return 0; }
static int tcp_exchange(int fd, fence_auth_type_t auth, void *key, size_t key_len, int timeout) { fd_set rfds; struct timeval tv; char ret = 1; /* Ok, we're connected */ dbg_printf(3, "Issuing TCP challenge\n"); if (tcp_challenge(fd, auth, key, key_len, timeout) <= 0) { /* Challenge failed */ printf("Invalid response to challenge\n"); return 1; } /* Now they'll send us one, so we need to respond here */ dbg_printf(3, "Responding to TCP challenge\n"); if (tcp_response(fd, auth, key, key_len, timeout) <= 0) { printf("Invalid response to challenge\n"); return 1; } dbg_printf(2, "TCP Exchange + Authentication done... \n"); FD_ZERO(&rfds); FD_SET(fd, &rfds); tv.tv_sec = timeout; tv.tv_usec = 0; ret = 1; dbg_printf(3, "Waiting for return value from XVM host\n"); if (_select_retry(fd + 1, &rfds, NULL, NULL, &tv) <= 0) return -1; /* Read return code */ if (_read_retry(fd, &ret, 1, &tv) < 0) ret = 1; if (ret == (char)RESP_HOSTLIST) /* hostlist */ { do_read_hostlist(fd, timeout); ret = 0; } return ret; }
static int vsock_dispatch(listener_context_t c, struct timeval *timeout) { vsock_info *info; fence_req_t data; fd_set rfds; int n; int client_fd; int ret; struct timeval tv; if (timeout != NULL) memcpy(&tv, timeout, sizeof(tv)); else { tv.tv_sec = 1; tv.tv_usec = 0; } info = (vsock_info *) c; VALIDATE(info); FD_ZERO(&rfds); FD_SET(info->listen_sock, &rfds); n = select(info->listen_sock + 1, &rfds, NULL, NULL, timeout); if (n <= 0) { if (errno == EINTR || errno == EAGAIN) n = 0; else dbg_printf(2, "select: %s\n", strerror(errno)); return n; } client_fd = accept(info->listen_sock, NULL, NULL); if (client_fd < 0) { perror("accept"); return -1; } dbg_printf(3, "Accepted vsock client...\n"); ret = _read_retry(client_fd, &data, sizeof(data), &tv); if (ret != sizeof(data)) { dbg_printf(3, "Invalid request (read %d bytes)\n", ret); close(client_fd); return 0; } swab_fence_req_t(&data); if (!verify_request(&data, info->args.hash, info->key, info->key_len)) { printf("Key mismatch; dropping client\n"); close(client_fd); return 0; } dbg_printf(3, "Request %d seqno %d domain %s\n", data.request, data.seqno, data.domain); if (history_check(info->history, &data) == 1) { printf("We just did this request; dropping client\n"); close(client_fd); return 0; } switch(info->args.auth) { case AUTH_NONE: case AUTH_SHA1: case AUTH_SHA256: case AUTH_SHA512: printf("VSOCK request\n"); do_fence_request_vsock(client_fd, &data, info); break; default: printf("XXX Unhandled authentication\n"); } return 0; }
int serial_fence_virt(fence_virt_args_t *args) { struct in_addr ina; struct in6_addr in6a; serial_req_t req; int fd, ret; char speed[32], *flags = NULL; struct timeval tv; serial_resp_t resp; if (args->serial.device) { strncpy(speed, args->serial.speed, sizeof(speed)); //printf("Port: %s Speed: %s\n", args->serial.device, speed); if ((flags = strchr(speed, ','))) { *flags = 0; flags++; } fd = open_port(args->serial.device, speed, flags); if (fd == -1) { perror("open_port"); return -1; } hangup(fd, 300000); } else { fd = -1; if (inet_pton(PF_INET, args->serial.address, &ina)) { fd = ipv4_connect(&ina, args->net.port, 3); } else if (inet_pton(PF_INET6, args->serial.address, &in6a)) { fd = ipv6_connect(&in6a, args->net.port, 3); } if (fd < 0) { perror("vmchannel connect"); printf("Failed to connect to %s:%d\n", args->serial.address, args->net.port); } } memset(&req, 0, sizeof(req)); req.magic = SERIAL_MAGIC; req.request = (uint8_t)args->op; gettimeofday(&tv, NULL); req.seqno = (int)tv.tv_usec; if (args->domain) strncpy((char *)req.domain, args->domain, sizeof(req.domain)); tv.tv_sec = 3; tv.tv_usec = 0; swab_serial_req_t(&req); ret = _write_retry(fd, &req, sizeof(req), &tv); if (ret < sizeof(req)) { if (ret < 0) return ret; printf("Failed to send request\n"); } tv.tv_sec = args->timeout; tv.tv_usec = 0; resp.magic = SERIAL_MAGIC; do { if (wait_for(fd, (const char *)&resp.magic, sizeof(resp.magic), &tv) == 0) { ret = _read_retry(fd, &resp.response, sizeof(resp.response), &tv); } swab_serial_resp_t(&resp); } while(resp.magic != SERIAL_MAGIC && (tv.tv_sec || tv.tv_usec)); if (resp.magic != SERIAL_MAGIC) return -1; ret = resp.response; if (resp.response == RESP_HOSTLIST) /* hostlist */ { /* ok read hostlist */ do_read_hostlist(fd, args->timeout); ret = 0; } close(fd); return ret; }