static int mcast_hostlist(const char *vm_name, const char *vm_uuid, int state, void *priv) { struct mcast_hostlist_arg *arg = (struct mcast_hostlist_arg *)priv; host_state_t hinfo; struct timeval tv; int ret; if (map_check(arg->map, arg->src, vm_uuid) == 0) { /* if we don't have access to fence this VM, * we should not see it in a hostlist either */ return 0; } strncpy((char *)hinfo.domain, vm_name, sizeof(hinfo.domain)); strncpy((char *)hinfo.uuid, vm_uuid, sizeof(hinfo.uuid)); hinfo.state = state; tv.tv_sec = 1; tv.tv_usec = 0; ret = _write_retry(arg->fd, &hinfo, sizeof(hinfo), &tv); if (ret == sizeof(hinfo)) return 0; return 1; }
static int vsock_hostlist_begin(int fd) { struct timeval tv; char val = (char) RESP_HOSTLIST; tv.tv_sec = 1; tv.tv_usec = 0; return _write_retry(fd, &val, 1, &tv); }
static int vsock_hostlist_end(int fd) { host_state_t hinfo; struct timeval tv; int ret; printf("Sending terminator packet\n"); memset(&hinfo, 0, sizeof(hinfo)); tv.tv_sec = 1; tv.tv_usec = 0; ret = _write_retry(fd, &hinfo, sizeof(hinfo), &tv); if (ret == sizeof(hinfo)) return 0; return 1; }
static int vsock_hostlist(const char *vm_name, const char *vm_uuid, int state, void *priv) { struct vsock_hostlist_arg *arg = (struct vsock_hostlist_arg *) priv; host_state_t hinfo; struct timeval tv; int ret; uint32_t peer_cid = 0; char peer_cid_str[24]; ret = get_peer_cid(arg->fd, &peer_cid); if (ret < 0) { printf("Unable to get peer CID: %s\n", strerror(errno)); peer_cid_str[0] = '\0'; } else snprintf(peer_cid_str, sizeof(peer_cid_str), "%u", peer_cid); /* Noops if auth == AUTH_NONE */ if (map_check(arg->map, peer_cid_str, vm_uuid) == 0) { /* if we don't have access to fence this VM, * we should not see it in a hostlist either */ return 0; } strncpy((char *)hinfo.domain, vm_name, sizeof(hinfo.domain)); strncpy((char *)hinfo.uuid, vm_uuid, sizeof(hinfo.uuid)); hinfo.state = state; tv.tv_sec = 1; tv.tv_usec = 0; ret = _write_retry(arg->fd, &hinfo, sizeof(hinfo), &tv); if (ret == sizeof(hinfo)) return 0; return 1; }
static int do_fence_request_vsock(int fd, fence_req_t *req, vsock_info *info) { char response = 1; struct vsock_hostlist_arg arg; uint32_t peer_cid = 0; char peer_cid_str[24]; int ret; ret = get_peer_cid(fd, &peer_cid); if (ret < 0) { printf("Unable to get peer CID: %s\n", strerror(errno)); return -1; } snprintf(peer_cid_str, sizeof(peer_cid_str), "%u", peer_cid); /* Noops if auth == AUTH_NONE */ if (sock_response(fd, info->args.auth, info->key, info->key_len, 10) <= 0) { printf("CID %u Failed to respond to challenge\n", peer_cid); close(fd); return -1; } ret = sock_challenge(fd, info->args.auth, info->key, info->key_len, 10); if (ret <= 0) { printf("Remote CID %u failed challenge\n", peer_cid); close(fd); return -1; } dbg_printf(2, "Request %d seqno %d target %s from CID %u\n", req->request, req->seqno, req->domain, peer_cid); switch(req->request) { case FENCE_NULL: response = info->cb->null((char *)req->domain, info->priv); break; case FENCE_ON: if (map_check(info->map, peer_cid_str, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->on((char *)req->domain, peer_cid_str, req->seqno, info->priv); break; case FENCE_OFF: if (map_check(info->map, peer_cid_str, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->off((char *)req->domain, peer_cid_str, req->seqno, info->priv); break; case FENCE_REBOOT: if (map_check(info->map, peer_cid_str, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->reboot((char *)req->domain, peer_cid_str, req->seqno, info->priv); break; case FENCE_STATUS: if (map_check(info->map, peer_cid_str, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->status((char *)req->domain, info->priv); break; case FENCE_DEVSTATUS: response = info->cb->devstatus(info->priv); break; case FENCE_HOSTLIST: arg.map = info->map; arg.fd = fd; vsock_hostlist_begin(arg.fd); response = info->cb->hostlist(vsock_hostlist, &arg, info->priv); vsock_hostlist_end(arg.fd); break; } dbg_printf(3, "Sending response to caller CID %u...\n", peer_cid); if (_write_retry(fd, &response, 1, NULL) < 0) perror("write"); history_record(info->history, req); if (fd != -1) close(fd); return 1; }
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; }