--- a/fence/agents/xvm/Makefile +++ b/fence/agents/xvm/Makefile @@ -1,12 +1,9 @@ -TARGET1= fence_xvm -TARGET2= fence_xvmd -TARGET3= testprog +TARGET1= fence_xvmd +TARGET2= testprog -SBINDIRT=$(TARGET1) $(TARGET2) +SBINDIRT=$(TARGET1) -MANTARGET= fence_xvm.8 - -all: ${TARGET1} ${TARGET2} ${MANTARGET} +all: ${TARGET1} include ../../../make/defines.mk include $(OBJDIR)/make/cobj.mk @@ -14,22 +11,19 @@ include $(OBJDIR)/make/clean.mk include $(OBJDIR)/make/install.mk include $(OBJDIR)/make/uninstall.mk -OBJS1= fence_xvm.o \ - ip_lookup.o - -OBJS2= fence_xvmd.o \ +OBJS1= fence_xvmd.o \ virt.o \ options-ccs.o \ vm_states.o \ - xml.o + xml.o \ + mcast.o \ + simple_auth.o \ + tcp.o \ + options.o \ + debug.o -OBJS3= xml-standalone.o -SHAREDOBJS= mcast.o \ - simple_auth.o \ - tcp.o \ - options.o \ - debug.o +OBJS2= xml-standalone.o CFLAGS += -D_GNU_SOURCE CFLAGS += -I${ccsincdir} -I${cmanincdir} @@ -44,30 +38,19 @@ STANDALONE_CFLAGS += -DSTANDALONE LDFLAGS += -L${nsslibdir} -lnss3 LDFLAGS += -L${logtlibdir} -llogthread LDFLAGS += -L${libdir} +LDFLAGS += -L${ccslibdir} -lccs -L${cmanlibdir} -lcman +LDFLAGS += -L${virtlibdir} -lvirt +LDFLAGS += -L${openaislibdir} -lSaCkpt -EXTRA_LDFLAGS += -L${ccslibdir} -lccs -L${cmanlibdir} -lcman -EXTRA_LDFLAGS += -L${virtlibdir} -lvirt -EXTRA_LDFLAGS += -L${openaislibdir} -lSaCkpt XML_LDFLAGS += `xml2-config --libs` ${TARGET1}: ${SHAREDOBJS} ${OBJS1} - $(CC) -o $@ $^ $(LDFLAGS) + $(CC) -o $@ $^ $(XML_LDFLAGS) $(LDFLAGS) -${TARGET2}: ${SHAREDOBJS} ${OBJS2} - $(CC) -o $@ $^ $(EXTRA_LDFLAGS) $(XML_LDFLAGS) $(LDFLAGS) - -${TARGET3}: ${OBJS3} +${TARGET2}: ${OBJS2} $(CC) -o $@ $^ $(XML_LDFLAGS) -$(MANTARGET): $(TARGET1) ${SRCDIR}/fence/agents/lib/fence2man.xsl - set -e && \ - LD_LIBRARY_PATH=${logtlibdir} ./$(TARGET1) -o metadata > .$@.tmp && \ - xsltproc ${SRCDIR}/fence/agents/lib/fence2man.xsl .$@.tmp > $@ - clean: generalclean - rm -f $(MANTARGET) .$(MANTARGET).tmp -include $(OBJS1:.o=.d) -include $(OBJS2:.o=.d) --include $(OBJS3:.o=.d) --include $(SHAREDOBJS:.o=.d) --- a/fence/agents/xvm/fence_xvm.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * @file fence_xvmd.c: Implementation of server daemon for Xen virtual - * machine fencing. This uses SA AIS CKPT b.1.0 checkpointing API to - * store virtual machine states. - * - * Author: Lon Hohberger - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Local includes */ -#include "xvm.h" -#include "ip_lookup.h" -#include "simple_auth.h" -#include "options.h" -#include "tcp.h" -#include "mcast.h" -#include "debug.h" - -#define LOG_DAEMON_NAME "fence_xvm" - -static int -tcp_wait_connect(int lfd, int retry_tenths) -{ - int fd; - fd_set rfds; - int n; - struct timeval tv; - - dbg_printf(3, "Waiting for connection from XVM host daemon.\n"); - FD_ZERO(&rfds); - FD_SET(lfd, &rfds); - tv.tv_sec = retry_tenths / 10; - tv.tv_usec = (retry_tenths % 10) * 100000; - - n = select(lfd + 1, &rfds, NULL, NULL, &tv); - if (n == 0) { - errno = ETIMEDOUT; - return -1; - } else if (n < 0) { - return -1; - } - - fd = accept(lfd, NULL, 0); - if (fd < 0) - return -1; - - return fd; -} - - -static int -tcp_exchange(int fd, fence_auth_type_t auth, void *key, - size_t key_len, int timeout) -{ - char ret; - fd_set rfds; - struct timeval tv; - - /* Ok, we're connected */ - dbg_printf(3, "Issuing TCP challenge\n"); - if (tcp_challenge(fd, auth, key, key_len, timeout) <= 0) { - /* Challenge failed */ - logt_print(LOG_ERR, "Invalid response to challenge\n"); - return 0; - } - - /* 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) { - logt_print(LOG_ERR, "Invalid response to challenge\n"); - return 0; - } - - 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(fd + 1, &rfds, NULL, NULL, &tv) <= 0) - return -1; - - /* Read return code */ - if (read(fd, &ret, 1) < 0) - return -1; - - close(fd); - if (ret == 0) - logt_print(LOG_INFO, "Remote: Operation was successful\n"); - else - logt_print(LOG_INFO, "Remote: Operation failed\n"); - return ret; -} - - -static int -send_multicast_packets(ip_list_t *ipl, fence_xvm_args_t *args, void *key, - size_t key_len) -{ - fence_req_t freq; - int mc_sock; - ip_addr_t *ipa; - struct sockaddr_in tgt4; - struct sockaddr_in6 tgt6; - struct sockaddr *tgt; - socklen_t tgt_len; - - for (ipa = ipl->tqh_first; ipa; ipa = ipa->ipa_entries.tqe_next) { - - if (ipa->ipa_family != args->family) { - dbg_printf(2, "Ignoring %s: wrong family\n", ipa->ipa_address); - continue; - } - - if (args->family == PF_INET) { - mc_sock = ipv4_send_sk(ipa->ipa_address, args->addr, - args->port, - (struct sockaddr *)&tgt4, - sizeof(struct sockaddr_in), - args->ttl); - tgt = (struct sockaddr *)&tgt4; - tgt_len = sizeof(tgt4); - - } else if (args->family == PF_INET6) { - mc_sock = ipv6_send_sk(ipa->ipa_address, args->addr, - args->port, - (struct sockaddr *)&tgt6, - sizeof(struct sockaddr_in6), - args->ttl); - tgt = (struct sockaddr *)&tgt6; - tgt_len = sizeof(tgt6); - } else { - dbg_printf(2, "Unsupported family %d\n", args->family); - return -1; - } - - if (mc_sock < 0) - continue; - - /* Build our packet */ - memset(&freq, 0, sizeof(freq)); - strncpy((char *)freq.domain, args->domain, - sizeof(freq.domain)); - freq.request = args->op; - freq.hashtype = args->hash; - - /* Store source address */ - if (ipa->ipa_family == PF_INET) { - freq.addrlen = sizeof(struct in_addr); - /* XXX Swap order for in_addr ? XXX */ - inet_pton(PF_INET, ipa->ipa_address, freq.address); - } else if (ipa->ipa_family == PF_INET6) { - freq.addrlen = sizeof(struct in6_addr); - inet_pton(PF_INET6, ipa->ipa_address, freq.address); - } - - freq.flags = 0; - if (args->flags & F_USE_UUID) - freq.flags |= RF_UUID; - freq.family = ipa->ipa_family; - freq.port = args->port; - - sign_request(&freq, key, key_len); - - dbg_printf(3, "Sending to %s via %s\n", args->addr, - ipa->ipa_address); - - sendto(mc_sock, &freq, sizeof(freq), 0, - (struct sockaddr *)tgt, tgt_len); - - close(mc_sock); - } - - return 0; -} - - -/* TODO: Clean this up!!! */ -static int -fence_xen_domain(fence_xvm_args_t *args) -{ - ip_list_t ipl; - char key[MAX_KEY_LEN]; - int lfd, key_len = 0, fd; - int attempts = 0; - - if (args->auth != AUTH_NONE || args->hash != HASH_NONE) { - key_len = read_key_file(args->key_file, key, sizeof(key)); - if (key_len < 0) { - logt_print(LOG_INFO, - "Could not read %s; trying without " - "authentication\n", args->key_file); - args->auth = AUTH_NONE; - args->hash = HASH_NONE; - } - } - - /* Do the real work */ - if (ip_build_list(&ipl) < 0) { - logt_print(LOG_ERR, "Error building IP address list\n"); - return 1; - } - - switch (args->auth) { - case AUTH_NONE: - case AUTH_SHA1: - case AUTH_SHA256: - case AUTH_SHA512: - if (args->family == PF_INET) { - lfd = ipv4_listen(args->port, 10); - } else { - lfd = ipv6_listen(args->port, 10); - } - break; - /*case AUTH_X509:*/ - /* XXX Setup SSL listener socket here */ - default: - return 1; - } - - if (lfd < 0) { - logt_print(LOG_ERR, "Failed to listen: %s\n", strerror(errno)); - return 1; - } - - attempts = args->timeout * 10 / args->retr_time; - - logt_print(LOG_INFO, "Sending fence request for %s\n", - args->domain); - - do { - if (send_multicast_packets(&ipl, args, key, key_len)) { - return -1; - } - - switch (args->auth) { - case AUTH_NONE: - case AUTH_SHA1: - case AUTH_SHA256: - case AUTH_SHA512: - fd = tcp_wait_connect(lfd, args->retr_time); - if (fd < 0 && (errno == ETIMEDOUT || - errno == EINTR)) - continue; - break; - /* case AUTH_X509: - ... = ssl_wait_connect... */ - break; - default: - return 1; - } - - break; - } while (--attempts); - - if (fd < 0) { - if (attempts <= 0) { - logt_print(LOG_ERR, - "Timed out waiting for response\n"); - return 1; - } - logt_print(LOG_ERR, "Fencing failed: %s\n", strerror(errno)); - return -1; - } - - switch (args->auth) { - case AUTH_NONE: - case AUTH_SHA1: - case AUTH_SHA256: - case AUTH_SHA512: - return tcp_exchange(fd, args->auth, key, key_len, - args->timeout); - break; - /* case AUTH_X509: - return ssl_exchange(...); */ - default: - return 1; - } - - return 1; -} - - -int -main(int argc, char **argv) -{ - fence_xvm_args_t args; - const char *my_options = "di:a:p:T:r:C:c:k:H:uo:t:?hV"; - - /* Print to stderr. Fenced will report our output for us */ - logt_init(LOG_DAEMON_NAME, LOG_MODE_OUTPUT_STDERR, - SYSLOGFACILITY, SYSLOGLEVEL, SYSLOGLEVEL, NULL); - - args_init(&args); - - if (argc == 1) { - args_get_stdin(my_options, &args); - } else { - args_get_getopt(argc, argv, my_options, &args); - } - - if (args.flags & F_HELP) { - args_usage(argv[0], my_options, 0); - - printf("With no command line argument, arguments are " - "read from standard input.\n"); - printf("Arguments read from standard input take " - "the form of:\n\n"); - printf(" arg1=value1\n"); - printf(" arg2=value2\n\n"); - - args_usage(argv[0], my_options, 1); - exit(0); - } - - if (args.flags & F_METADATA) { - args_metadata(argv[0], my_options); - exit(0); - } - - if (args.flags & F_VERSION) { - printf("%s %s\n", basename(argv[0]), XVM_VERSION); - printf("fence release %s\n", RELEASE_VERSION); - exit(0); - } - - args_finalize(&args); - dset(args.debug); - - if (args.debug > 0) { - logt_conf(LOG_DAEMON_NAME, LOG_MODE_OUTPUT_STDERR, - SYSLOGFACILITY, LOG_DEBUG, LOG_DEBUG, NULL); - args_print(&args); - } - - /* Additional validation here */ - if (!args.domain) { - logt_print(LOG_ERR, "No domain specified!\n"); - args.flags |= F_ERR; - } - - if (args.flags & F_ERR) { - args_usage(argv[0], my_options, (argc == 1)); - exit(1); - } - - /* Initialize NSS; required to do hashing, as silly as that - sounds... */ - if (NSS_NoDB_Init(NULL) != SECSuccess) { - logt_print(LOG_ERR, "Could not initialize NSS\n"); - return 1; - } - - return fence_xen_domain(&args); -} --- a/fence/agents/xvm/ip_lookup.c +++ /dev/null @@ -1,307 +0,0 @@ -/** @file - * Build lists of IPs on the system, excepting loopback ipv6 link-local - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef IFA_MAX -#include -#endif - -/* Local includes */ -#include "ip_lookup.h" -#include "debug.h" - -static int -send_addr_dump(int fd, int family) -{ - struct nlmsghdr *nh; - struct rtgenmsg *g; - char buf[256]; - struct sockaddr_nl addr; - - memset(&addr,0,sizeof(addr)); - addr.nl_family = PF_NETLINK; - - memset(buf, 0, sizeof(buf)); - nh = (struct nlmsghdr *)buf; - g = (struct rtgenmsg *)(buf + sizeof(struct nlmsghdr)); - - nh->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); - nh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP; - nh->nlmsg_type = RTM_GETADDR; - g->rtgen_family = family; - - return sendto(fd, buf, nh->nlmsg_len, 0, (struct sockaddr *)&addr, - sizeof(addr)); -} - - -static int -add_ip(ip_list_t *ipl, char *ipaddr, char family) -{ - ip_addr_t *ipa; - - if (family == PF_INET6) { - /* Avoid loopback */ - if (!strcmp(ipaddr, "::1")) - return -1; - - /* Avoid link-local addresses */ - if (!strncmp(ipaddr, "fe80", 4)) - return -1; - if (!strncmp(ipaddr, "fe90", 4)) - return -1; - if (!strncmp(ipaddr, "fea0", 4)) - return -1; - if (!strncmp(ipaddr, "feb0", 4)) - return -1; - } - - dbg_printf(4, "Adding IP %s to list (family %d)\n", ipaddr, family); - - ipa = malloc(sizeof(*ipa)); - if (!ipa) - return -1; - memset(ipa, 0, sizeof(*ipa)); - ipa->ipa_family = family; - ipa->ipa_address = strdup(ipaddr); - - TAILQ_INSERT_TAIL(ipl, ipa, ipa_entries); - - return 0; -} - - -static int -add_ip_addresses(int family, ip_list_t *ipl) -{ - /* List ipv4 addresses */ - struct nlmsghdr *nh; - struct ifaddrmsg *ifa; - struct rtattr *rta, *nrta; - struct nlmsgerr *err; - char buf[10240]; - char outbuf[256]; - int x, fd, len; - - dbg_printf(5, "Connecting to Netlink...\n"); - fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - perror("socket"); - exit(1); - } - - dbg_printf(5, "Sending address dump request\n"); - send_addr_dump(fd, family); - memset(buf, 0, sizeof(buf)); - - dbg_printf(5, "Waiting for response\n"); - x = recvfrom(fd, buf, sizeof(buf), 0, NULL, 0); - if (x < 0) { - perror("recvfrom"); - return -1; - } - - dbg_printf(5, "Received %d bytes\n", x); - - nh = (struct nlmsghdr *)buf; - while (NLMSG_OK(nh, x)) { - - switch(nh->nlmsg_type) { - case NLMSG_DONE: - close(fd); - return 0; - - case NLMSG_ERROR: - err = (struct nlmsgerr*)NLMSG_DATA(nh); - if (nh->nlmsg_len < - NLMSG_LENGTH(sizeof(struct nlmsgerr))) { - fprintf(stderr, "ERROR truncated"); - } else { - errno = -err->error; - perror("RTNETLINK answers"); - } - close(fd); - return -1; - - case RTM_NEWADDR: - break; - - default: - nh = NLMSG_NEXT(nh, x); - continue; - } - - /* RTM_NEWADDR */ - len = NLMSG_PAYLOAD(nh,0); - ifa = NLMSG_DATA(nh); - - /* Make sure we got the type we expect back */ - if (ifa->ifa_family != family) { - nh = NLMSG_NEXT(nh, x); - continue; - } - - rta = (struct rtattr *)((char *)ifa + sizeof(*ifa)); - len -= sizeof(*ifa); - do { - /* Make sure we've got a valid rtaddr field */ - if (!RTA_OK(rta, len)) { - dbg_printf(5, "!RTA_OK(rta, len)\n"); - break; - } - - if (rta->rta_type == IFA_ADDRESS) { - inet_ntop(family, RTA_DATA(rta), outbuf, - sizeof(outbuf) ); - add_ip(ipl, outbuf, family); - } - - if (rta->rta_type == IFA_LABEL) { - dbg_printf(5, "Skipping label: %s\n", - (char *)RTA_DATA(rta)); - } - - nrta = RTA_NEXT(rta, len); - if (!nrta) - break; - - len -= ((char *)nrta - (char *)rta); - rta = nrta; - } while (RTA_OK(rta, len)); - - nh = NLMSG_NEXT(nh, x); - } - - dbg_printf(5, "Closing Netlink connection\n"); - close(fd); - return 0; -} - - -int -ip_search(ip_list_t *ipl, char *ip_name) -{ - ip_addr_t *ipa; - - dbg_printf(5, "Looking for IP address %s in IP list %p...", ip_name, ipl); - ipa = ipl->tqh_first; - for (ipa = ipl->tqh_first; ipa; ipa = ipa->ipa_entries.tqe_next) { - if (!strcmp(ip_name, ipa->ipa_address)) { - dbg_printf(4,"Found\n"); - return 0; - } - } - dbg_printf(5, "Not found\n"); - return 1; -} - - -int -ip_free_list(ip_list_t *ipl) -{ - ip_addr_t *ipa; - - dbg_printf(5, "Tearing down IP list @ %p\n", ipl); - while ((ipa = ipl->tqh_first)) { - TAILQ_REMOVE(ipl, ipa, ipa_entries); - free(ipa->ipa_address); - free(ipa); - } - return 0; -} - - -int -ip_build_list(ip_list_t *ipl) -{ - dbg_printf(5, "Build IP address list\n"); - TAILQ_INIT(ipl); - if (add_ip_addresses(PF_INET6, ipl) < 0) { - ip_free_list(ipl); - return -1; - } - if (add_ip_addresses(PF_INET, ipl) < 0) { - ip_free_list(ipl); - return -1; - } - return 0; -} - - -/** - Look up the interface name which corresponds to the given hostname and - return the list of matching attrinfo structures. We do this by looking - up all the possible physical and virtual network interfaces on the machine - and checking the hostname/IP mappings for each active IP address incurred. - - @param nodename Interface name - @param ret_ai Structure pointer to allocate & return. - @return -1 on failure or 0 on success. - */ -int -ip_lookup(char *nodename, struct addrinfo **ret_ai) -{ - char ip_name[256]; - struct addrinfo *ai = NULL; - struct addrinfo *n; - void *p; - ip_list_t ipl; - int ret = -1; - - dbg_printf(5, "Looking for IP matching %s\n", nodename); - /* Build list of IP addresses configured locally */ - if (ip_build_list(&ipl) < 0) - return -1; - - /* Get list of addresses for the host-name/ip */ - if (getaddrinfo(nodename, NULL, NULL, &ai) != 0) - return -1; - - - /* Traverse list of addresses for given host-name/ip */ - for (n = ai; n; n = n->ai_next) { - if (n->ai_family != PF_INET && n->ai_family != PF_INET6) - continue; - - if (n->ai_family == PF_INET) - p = &(((struct sockaddr_in *)n->ai_addr)->sin_addr); - else - p = &(((struct sockaddr_in6 *)n->ai_addr)->sin6_addr); - - if (!inet_ntop(n->ai_family, p, ip_name, - sizeof(ip_name))) - continue; - - /* Search local interfaces for this IP address */ - if (ip_search(&ipl, ip_name) != 0) - continue; - - /* Found it */ - ret = 0; - break; - } - - /* Clean up */ - if (!ret_ai) - freeaddrinfo(ai); - else - *ret_ai = ai; - - ip_free_list(&ipl); - - return ret; -} - --- a/fence/agents/xvm/ip_lookup.h +++ /dev/null @@ -1,22 +0,0 @@ -/** @file - * Header for ip_lookup.c - */ -#ifndef _IP_LOOKUP_H -#define _IP_LOOKUP_H - -#include - -typedef struct _ip_address { - TAILQ_ENTRY(_ip_address) ipa_entries; - char ipa_family; - char *ipa_address; -} ip_addr_t; - -typedef TAILQ_HEAD(_ip_list, _ip_address) ip_list_t; - -int ip_search(ip_list_t *ipl, char *ip_name); -int ip_free_list(ip_list_t *ipl); -int ip_build_list(ip_list_t *ipl); -int ip_lookup(char *, struct addrinfo **); - -#endif