diff --git a/exec/totemip.c b/exec/totemip.c index 1e1ea080..c285a736 100644 --- a/exec/totemip.c +++ b/exec/totemip.c @@ -1,631 +1,627 @@ /* * Copyright (c) 2005-2020 Red Hat, Inc. * * All rights reserved. * * Author: Patrick Caulfield (pcaulfie@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /* IPv4/6 abstraction */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define LOCALHOST_IPV4 "127.0.0.1" #define LOCALHOST_IPV6 "::1" #define NETLINK_BUFSIZE 16384 #ifdef SO_NOSIGPIPE void totemip_nosigpipe(int s) { int on = 1; setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on)); } #endif /* Compare two addresses */ int totemip_equal(const struct totem_ip_address *addr1, const struct totem_ip_address *addr2) { int addrlen = 0; if (addr1->family != addr2->family) return 0; if (addr1->family == AF_INET) { addrlen = sizeof(struct in_addr); } if (addr1->family == AF_INET6) { addrlen = sizeof(struct in6_addr); } assert(addrlen); if (memcmp(addr1->addr, addr2->addr, addrlen) == 0) return 1; else return 0; } int totemip_sa_equal(const struct totem_ip_address *totem_ip, const struct sockaddr *sa) { int res; res = 0; if (totem_ip->family != sa->sa_family) { return (res); } switch (totem_ip->family) { case AF_INET: res = (memcmp(totem_ip->addr, &((const struct sockaddr_in *)sa)->sin_addr, sizeof(struct in_addr)) == 0); break; case AF_INET6: res = (memcmp(totem_ip->addr, &((const struct sockaddr_in6 *)sa)->sin6_addr, sizeof(struct in6_addr)) == 0); break; default: assert(0); } return (res); } /* Copy a totem_ip_address */ void totemip_copy(struct totem_ip_address *addr1, const struct totem_ip_address *addr2) { memcpy(addr1, addr2, sizeof(struct totem_ip_address)); } /* * Multicast address range is 224.0.0.0 to 239.255.255.255 this * translates to the first 4 bits == 1110 (0xE). * http://en.wikipedia.org/wiki/Multicast_address */ int32_t totemip_is_mcast(struct totem_ip_address *ip_addr) { uint32_t addr = 0; memcpy (&addr, ip_addr->addr, sizeof (uint32_t)); if (ip_addr->family == AF_INET) { addr = ntohl(addr); if ((addr >> 28) != 0xE) { return -1; } } return 0; } /* For sorting etc. params are void * for qsort's benefit */ int totemip_compare(const void *a, const void *b) { int i; const struct totem_ip_address *totemip_a = (const struct totem_ip_address *)a; const struct totem_ip_address *totemip_b = (const struct totem_ip_address *)b; struct in_addr ipv4_a1; struct in_addr ipv4_a2; struct in6_addr ipv6_a1; struct in6_addr ipv6_a2; unsigned short family; /* * Use memcpy to align since totem_ip_address is unaligned on various archs */ memcpy (&family, &totemip_a->family, sizeof (unsigned short)); if (family == AF_INET) { memcpy (&ipv4_a1, totemip_a->addr, sizeof (struct in_addr)); memcpy (&ipv4_a2, totemip_b->addr, sizeof (struct in_addr)); if (ipv4_a1.s_addr == ipv4_a2.s_addr) { return (0); } if (htonl(ipv4_a1.s_addr) < htonl(ipv4_a2.s_addr)) { return -1; } else { return +1; } } else if (family == AF_INET6) { /* * We can only compare 8 bits at time for portability reasons */ memcpy (&ipv6_a1, totemip_a->addr, sizeof (struct in6_addr)); memcpy (&ipv6_a2, totemip_b->addr, sizeof (struct in6_addr)); for (i = 0; i < 16; i++) { int res = ipv6_a1.s6_addr[i] - ipv6_a2.s6_addr[i]; if (res) { return res; } } return 0; } else { /* * Family not set, should be! */ assert (0); } return 0; } /* Build a localhost totem_ip_address */ int totemip_localhost(int family, struct totem_ip_address *localhost) { const char *addr_text; memset (localhost, 0, sizeof (struct totem_ip_address)); if (family == AF_INET) { addr_text = LOCALHOST_IPV4; if (inet_pton(family, addr_text, (char *)&localhost->nodeid) <= 0) { return -1; } } else { addr_text = LOCALHOST_IPV6; } if (inet_pton(family, addr_text, (char *)localhost->addr) <= 0) return -1; localhost->family = family; return 0; } int totemip_localhost_check(const struct totem_ip_address *addr) { struct totem_ip_address localhost; if (totemip_localhost(addr->family, &localhost)) return 0; return totemip_equal(addr, &localhost); } const char *totemip_sa_print(const struct sockaddr *sa) { static char buf[INET6_ADDRSTRLEN]; buf[0] = 0; switch (sa->sa_family) { case AF_INET: inet_ntop(sa->sa_family, &((struct sockaddr_in *)(sa))->sin_addr, buf, INET6_ADDRSTRLEN); break; case AF_INET6: inet_ntop(sa->sa_family, &((struct sockaddr_in6 *)(sa))->sin6_addr, buf, INET6_ADDRSTRLEN); break; default: return (NULL); } return (buf); } const char *totemip_print(const struct totem_ip_address *addr) { static char buf[INET6_ADDRSTRLEN]; return (inet_ntop(addr->family, addr->addr, buf, sizeof(buf))); } /* Make a totem_ip_address into a usable sockaddr_storage */ int totemip_totemip_to_sockaddr_convert(struct totem_ip_address *ip_addr, uint16_t port, struct sockaddr_storage *saddr, int *addrlen) { int ret = -1; if (ip_addr->family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in *)saddr; memset(sin, 0, sizeof(struct sockaddr_in)); #ifdef HAVE_SOCK_SIN_LEN sin->sin_len = sizeof(struct sockaddr_in); #endif sin->sin_family = ip_addr->family; sin->sin_port = ntohs(port); memcpy(&sin->sin_addr, ip_addr->addr, sizeof(struct in_addr)); *addrlen = sizeof(struct sockaddr_in); ret = 0; } if (ip_addr->family == AF_INET6) { struct sockaddr_in6 *sin = (struct sockaddr_in6 *)saddr; memset(sin, 0, sizeof(struct sockaddr_in6)); #ifdef HAVE_SOCK_SIN6_LEN sin->sin6_len = sizeof(struct sockaddr_in6); #endif sin->sin6_family = ip_addr->family; sin->sin6_port = ntohs(port); - sin->sin6_scope_id = ip_addr->sin6_scope_id; + sin->sin6_scope_id = 2; memcpy(&sin->sin6_addr, ip_addr->addr, sizeof(struct in6_addr)); *addrlen = sizeof(struct sockaddr_in6); ret = 0; } return ret; } /* * Converts an address string string into a totem_ip_address. ip_version enum * defines order. */ int totemip_parse(struct totem_ip_address *totemip, const char *addr, enum totem_ip_version_enum ip_version) { struct addrinfo *ainfo; struct addrinfo *ainfo_iter; struct addrinfo *ainfo_ipv4; struct addrinfo *ainfo_ipv6; struct addrinfo *ainfo_final; struct addrinfo ahints; struct sockaddr_in *sa; struct sockaddr_in6 *sa6; int ret; int debug_ip_family; int ai_family; memset(&ahints, 0, sizeof(ahints)); ahints.ai_socktype = SOCK_DGRAM; ahints.ai_protocol = IPPROTO_UDP; ai_family = AF_UNSPEC; debug_ip_family = 0; switch (ip_version) { case TOTEM_IP_VERSION_4: ai_family = AF_INET; debug_ip_family = 4; break; case TOTEM_IP_VERSION_6: ai_family = AF_INET6; debug_ip_family = 6; break; case TOTEM_IP_VERSION_6_4: case TOTEM_IP_VERSION_4_6: /* * ai_family and debug_ip_family are already set correctly */ break; } ahints.ai_family = ai_family; ret = getaddrinfo(addr, NULL, &ahints, &ainfo); if (ret == 0 && ai_family == AF_UNSPEC) { ainfo_ipv4 = ainfo_ipv6 = NULL; /* * Walk thru results and store first AF_INET and AF_INET6 */ for (ainfo_iter = ainfo; ainfo_iter != NULL; ainfo_iter = ainfo_iter->ai_next) { if (ainfo_iter->ai_family == AF_INET && ainfo_ipv4 == NULL) { ainfo_ipv4 = ainfo_iter; } if (ainfo_iter->ai_family == AF_INET6 && ainfo_ipv6 == NULL) { ainfo_ipv6 = ainfo_iter; } } if (ip_version == TOTEM_IP_VERSION_6_4) { if (ainfo_ipv6 != NULL) { ainfo_final = ainfo_ipv6; } else { ainfo_final = ainfo_ipv4; } } else { if (ainfo_ipv4 != NULL) { ainfo_final = ainfo_ipv4; } else { ainfo_final = ainfo_ipv6; } } } else if (ret == 0) { ainfo_final = ainfo; } else { ainfo_final = NULL; } if (ainfo_final == NULL) { if (ret == 0) { freeaddrinfo(ainfo); } if (debug_ip_family == 0) { log_printf(LOGSYS_LEVEL_DEBUG, "totemip_parse: IP address of %s not resolvable", addr); } else { log_printf(LOGSYS_LEVEL_DEBUG, "totemip_parse: IPv%u address of %s not resolvable", debug_ip_family, addr); } return (-1); } totemip->family = ainfo_final->ai_family; if (ainfo_final->ai_family == AF_INET) { sa = (struct sockaddr_in *)ainfo_final->ai_addr; memcpy(totemip->addr, &sa->sin_addr, sizeof(struct in_addr)); - totemip->sin6_scope_id = 0; debug_ip_family = 4; } else { sa6 = (struct sockaddr_in6 *)ainfo_final->ai_addr; memcpy(totemip->addr, &sa6->sin6_addr, sizeof(struct in6_addr)); - totemip->sin6_scope_id = sa6->sin6_scope_id; debug_ip_family = 6; } log_printf(LOGSYS_LEVEL_DEBUG, "totemip_parse: IPv%u address of %s resolved as %s", debug_ip_family, addr, totemip_print(totemip)); freeaddrinfo(ainfo); return (0); } /* Make a sockaddr_* into a totem_ip_address */ int totemip_sockaddr_to_totemip_convert(const struct sockaddr_storage *saddr, struct totem_ip_address *ip_addr) { int ret = -1; ip_addr->family = saddr->ss_family; ip_addr->nodeid = 0; if (saddr->ss_family == AF_INET) { const struct sockaddr_in *sin = (const struct sockaddr_in *)saddr; memcpy(ip_addr->addr, &sin->sin_addr, sizeof(struct in_addr)); - ip_addr->sin6_scope_id = 0; ret = 0; } if (saddr->ss_family == AF_INET6) { const struct sockaddr_in6 *sin = (const struct sockaddr_in6 *)saddr; memcpy(ip_addr->addr, &sin->sin6_addr, sizeof(struct in6_addr)); - ip_addr->sin6_scope_id = sin->sin6_scope_id; ret = 0; } return ret; } int totemip_getifaddrs(struct qb_list_head *addrs) { struct ifaddrs *ifap, *ifa; struct totem_ip_if_address *if_addr; if (getifaddrs(&ifap) != 0) return (-1); qb_list_init(addrs); for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL || ifa->ifa_netmask == NULL) continue ; if ((ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6) || (ifa->ifa_netmask->sa_family != AF_INET && ifa->ifa_netmask->sa_family != AF_INET6 && ifa->ifa_netmask->sa_family != 0)) continue ; if (ifa->ifa_netmask->sa_family == 0) { ifa->ifa_netmask->sa_family = ifa->ifa_addr->sa_family; } if_addr = malloc(sizeof(struct totem_ip_if_address)); if (if_addr == NULL) { goto error_free_ifaddrs; } qb_list_init(&if_addr->list); memset(if_addr, 0, sizeof(struct totem_ip_if_address)); if_addr->interface_up = ifa->ifa_flags & IFF_UP; if_addr->interface_num = if_nametoindex(ifa->ifa_name); if_addr->name = strdup(ifa->ifa_name); if (if_addr->name == NULL) { goto error_free_addr; } if (totemip_sockaddr_to_totemip_convert((const struct sockaddr_storage *)ifa->ifa_addr, &if_addr->ip_addr) == -1) { goto error_free_addr_name; } if (totemip_sockaddr_to_totemip_convert((const struct sockaddr_storage *)ifa->ifa_netmask, &if_addr->mask_addr) == -1) { goto error_free_addr_name; } qb_list_add_tail(&if_addr->list, addrs); } freeifaddrs(ifap); return (0); error_free_addr_name: free(if_addr->name); error_free_addr: free(if_addr); error_free_ifaddrs: totemip_freeifaddrs(addrs); freeifaddrs(ifap); return (-1); } void totemip_freeifaddrs(struct qb_list_head *addrs) { struct totem_ip_if_address *if_addr; struct qb_list_head *list, *tmp_iter; qb_list_for_each_safe(list, tmp_iter, addrs) { if_addr = qb_list_entry(list, struct totem_ip_if_address, list); free(if_addr->name); qb_list_del(&if_addr->list); free(if_addr); } qb_list_init(addrs); } int totemip_iface_check(struct totem_ip_address *bindnet, struct totem_ip_address *boundto, int *interface_up, int *interface_num, int mask_high_bit) { struct qb_list_head addrs; struct qb_list_head *list; struct totem_ip_if_address *if_addr; struct totem_ip_address bn_netaddr, if_netaddr; socklen_t addr_len; socklen_t si; int res = -1; int exact_match_found = 0; int net_match_found = 0; *interface_up = 0; *interface_num = 0; if (totemip_getifaddrs(&addrs) == -1) { return (-1); } qb_list_for_each(list, &addrs) { if_addr = qb_list_entry(list, struct totem_ip_if_address, list); if (bindnet->family != if_addr->ip_addr.family) continue ; addr_len = 0; switch (bindnet->family) { case AF_INET: addr_len = sizeof(struct in_addr); break; case AF_INET6: addr_len = sizeof(struct in6_addr); break; } if (addr_len == 0) continue ; if (bindnet->sin6_scope_id != 0 && bindnet->sin6_scope_id != if_addr->interface_num) continue; totemip_copy(&bn_netaddr, bindnet); totemip_copy(&if_netaddr, &if_addr->ip_addr); if (totemip_equal(&bn_netaddr, &if_netaddr)) { exact_match_found = 1; } for (si = 0; si < addr_len; si++) { bn_netaddr.addr[si] = bn_netaddr.addr[si] & if_addr->mask_addr.addr[si]; if_netaddr.addr[si] = if_netaddr.addr[si] & if_addr->mask_addr.addr[si]; } if (exact_match_found || (!net_match_found && totemip_equal(&bn_netaddr, &if_netaddr))) { totemip_copy(boundto, &if_addr->ip_addr); boundto->nodeid = bindnet->nodeid; *interface_up = if_addr->interface_up; *interface_num = if_addr->interface_num; net_match_found = 1; res = 0; if (exact_match_found) { goto finished; } } } finished: totemip_freeifaddrs(&addrs); return (res); } #define TOTEMIP_UDP_HEADER_SIZE 8 #define TOTEMIP_IPV4_HEADER_SIZE 20 #define TOTEMIP_IPV6_HEADER_SIZE 40 size_t totemip_udpip_header_size(int family) { size_t header_size; header_size = 0; switch (family) { case AF_INET: header_size = TOTEMIP_UDP_HEADER_SIZE + TOTEMIP_IPV4_HEADER_SIZE; break; case AF_INET6: header_size = TOTEMIP_UDP_HEADER_SIZE + TOTEMIP_IPV6_HEADER_SIZE; break; } return (header_size); } diff --git a/include/corosync/coroapi.h b/include/corosync/coroapi.h index 1ac0443a..9d14b7bd 100644 --- a/include/corosync/coroapi.h +++ b/include/corosync/coroapi.h @@ -1,527 +1,526 @@ /* * Copyright (c) 2008-2012 Red Hat, Inc. * * All rights reserved. * * Author: Steven Dake (sdake@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef COROAPI_H_DEFINED #define COROAPI_H_DEFINED #include #include #ifdef HAVE_SYS_UIO_H #include #endif #include #include #include /** * @brief The mar_message_source_t struct */ typedef struct { uint32_t nodeid __attribute__((aligned(8))); void *conn __attribute__((aligned(8))); } mar_message_source_t __attribute__((aligned(8))); /** * @brief swab_mar_message_source_t * @param to_swab */ static inline void swab_mar_message_source_t (mar_message_source_t *to_swab) { swab32 (to_swab->nodeid); /* * if it is from a byteswapped machine, then we can safely * ignore its conn info data structure since this is only * local to the machine */ to_swab->conn = NULL; } #ifndef TIMER_HANDLE_T /** * @brief corosync_timer_handle_t */ typedef qb_loop_timer_handle corosync_timer_handle_t; #define TIMER_HANDLE_T 1 #endif /** * @brief The corosync_tpg_group struct */ struct corosync_tpg_group { const void *group; size_t group_len; }; #define TOTEMIP_ADDRLEN (sizeof(struct in6_addr)) #define INTERFACE_MAX 8 #ifndef MESSAGE_QUEUE_MAX #ifdef HAVE_SMALL_MEMORY_FOOTPRINT #define PROCESSOR_COUNT_MAX 16 #define MESSAGE_SIZE_MAX 1024*64 #define MESSAGE_QUEUE_MAX 512 #else #define PROCESSOR_COUNT_MAX 384 #define MESSAGE_SIZE_MAX 1024*1024 #define MESSAGE_QUEUE_MAX ((4 * MESSAGE_SIZE_MAX) / totem_config->net_mtu) #endif /* HAVE_SMALL_MEMORY_FOOTPRINT */ #endif /* MESSAGE_QUEUE_MAX */ #define TOTEM_AGREED 0 #define TOTEM_SAFE 1 #define MILLI_2_NANO_SECONDS 1000000ULL #if !defined(TOTEM_IP_ADDRESS) /** * @brief The totem_ip_address struct */ struct totem_ip_address { unsigned int nodeid; unsigned short family; unsigned char addr[TOTEMIP_ADDRLEN]; - unsigned int sin6_scope_id; } __attribute__((packed)); #endif #if !defined(MEMB_RING_ID) /** * @brief The memb_ring_id struct */ struct memb_ring_id { unsigned int nodeid; unsigned long long seq; } __attribute__((packed)); #endif #if !defined(TOTEM_CONFIGURATION_TYPE) /** * @brief The totem_configuration_type enum */ enum totem_configuration_type { TOTEM_CONFIGURATION_REGULAR, TOTEM_CONFIGURATION_TRANSITIONAL }; #endif #if !defined(TOTEM_CALLBACK_TOKEN_TYPE) /** * @brief The totem_callback_token_type enum */ enum totem_callback_token_type { TOTEM_CALLBACK_TOKEN_RECEIVED = 1, TOTEM_CALLBACK_TOKEN_SENT = 2 }; #endif /** * @brief The cs_lib_flow_control enum */ enum cs_lib_flow_control { CS_LIB_FLOW_CONTROL_REQUIRED = 1, CS_LIB_FLOW_CONTROL_NOT_REQUIRED = 2 }; #define corosync_lib_flow_control cs_lib_flow_control #define COROSYNC_LIB_FLOW_CONTROL_REQUIRED CS_LIB_FLOW_CONTROL_REQUIRED #define COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED CS_LIB_FLOW_CONTROL_NOT_REQUIRED /** * @brief The cs_lib_allow_inquorate enum */ enum cs_lib_allow_inquorate { CS_LIB_DISALLOW_INQUORATE = 0, /* default */ CS_LIB_ALLOW_INQUORATE = 1 }; #if !defined (COROSYNC_FLOW_CONTROL_STATE) /** * @brief The cs_flow_control_state enum */ enum cs_flow_control_state { CS_FLOW_CONTROL_STATE_DISABLED, CS_FLOW_CONTROL_STATE_ENABLED }; #define corosync_flow_control_state cs_flow_control_state #define CS_FLOW_CONTROL_STATE_DISABLED CS_FLOW_CONTROL_STATE_DISABLED #define CS_FLOW_CONTROL_STATE_ENABLED CS_FLOW_CONTROL_STATE_ENABLED #endif /* COROSYNC_FLOW_CONTROL_STATE */ /** * @brief The cs_fatal_error_t enum. */ typedef enum { COROSYNC_FATAL_ERROR_EXIT = -1, COROSYNC_LIBAIS_SOCKET = -6, COROSYNC_LIBAIS_BIND = -7, COROSYNC_READKEY = -8, COROSYNC_INVALID_CONFIG = -9, COROSYNC_DYNAMICLOAD = -12, COROSYNC_OUT_OF_MEMORY = -15, COROSYNC_FATAL_ERR = -16 } cs_fatal_error_t; #define corosync_fatal_error_t cs_fatal_error_t; #ifndef QUORUM_H_DEFINED /** *@brief The quorum_callback_fn_t callback */ typedef void (*quorum_callback_fn_t) (int quorate, void *context); /** * @brief The quorum_callin_functions struct */ struct quorum_callin_functions { int (*quorate) (void); int (*register_callback) (quorum_callback_fn_t callback_fn, void *contexxt); int (*unregister_callback) (quorum_callback_fn_t callback_fn, void *context); }; /** * @brief The sync_callback_fn_t callback */ typedef void (*sync_callback_fn_t) ( const unsigned int *view_list, size_t view_list_entries, int primary_designated, struct memb_ring_id *ring_id); #endif /* QUORUM_H_DEFINED */ /** * @brief The corosync_api_v1 struct */ struct corosync_api_v1 { /* * Time and timer APIs */ int (*timer_add_duration) ( unsigned long long nanoseconds_in_future, void *data, void (*timer_nf) (void *data), corosync_timer_handle_t *handle); int (*timer_add_absolute) ( unsigned long long nanoseconds_from_epoch, void *data, void (*timer_fn) (void *data), corosync_timer_handle_t *handle); void (*timer_delete) ( corosync_timer_handle_t timer_handle); unsigned long long (*timer_time_get) (void); unsigned long long (*timer_expire_time_get) ( corosync_timer_handle_t timer_handle); /* * IPC APIs */ void (*ipc_source_set) (mar_message_source_t *source, void *conn); int (*ipc_source_is_local) (const mar_message_source_t *source); void *(*ipc_private_data_get) (void *conn); int (*ipc_response_send) (void *conn, const void *msg, size_t mlen); int (*ipc_response_iov_send) (void *conn, const struct iovec *iov, unsigned int iov_len); int (*ipc_dispatch_send) (void *conn, const void *msg, size_t mlen); int (*ipc_dispatch_iov_send) (void *conn, const struct iovec *iov, unsigned int iov_len); void (*ipc_refcnt_inc) (void *conn); void (*ipc_refcnt_dec) (void *conn); /* * Totem APIs */ unsigned int (*totem_nodeid_get) (void); int (*totem_family_get) (void); int (*totem_mcast) (const struct iovec *iovec, unsigned int iov_len, unsigned int guarantee); int (*totem_ifaces_get) ( unsigned int nodeid, unsigned int *interface_ids, struct totem_ip_address *interfaces, unsigned int interfaces_size, char ***status, unsigned int *iface_count); const char *(*totem_ifaces_print) (unsigned int nodeid); const char *(*totem_ip_print) (const struct totem_ip_address *addr); int (*totem_crypto_set) (const char *cipher_type, const char *hash_type); int (*totem_callback_token_create) ( void **handle_out, enum totem_callback_token_type type, int delete, int (*callback_fn) (enum totem_callback_token_type type, const void *), const void *data); /* * Totem open process groups API for those service engines * wanting their own groups */ int (*tpg_init) ( void **instance, void (*deliver_fn) ( unsigned int nodeid, const void *msg, unsigned int msg_len, int endian_conversion_required), void (*confchg_fn) ( enum totem_configuration_type configuration_type, const unsigned int *member_list, size_t member_list_entries, const unsigned int *left_list, size_t left_list_entries, const unsigned int *joined_list, size_t joined_list_entries, const struct memb_ring_id *ring_id)); int (*tpg_exit) ( void *instance); int (*tpg_join) ( void *instance, const struct corosync_tpg_group *groups, size_t group_cnt); int (*tpg_leave) ( void *instance, const struct corosync_tpg_group *groups, size_t group_cnt); int (*tpg_joined_mcast) ( void *totempg_groups_instance, const struct iovec *iovec, unsigned int iov_len, int guarantee); int (*tpg_joined_reserve) ( void *totempg_groups_instance, const struct iovec *iovec, unsigned int iov_len); int (*tpg_joined_release) ( int reserved_msgs); int (*tpg_groups_mcast) ( void *instance, int guarantee, const struct corosync_tpg_group *groups, size_t groups_cnt, const struct iovec *iovec, unsigned int iov_len); int (*tpg_groups_reserve) ( void *instance, const struct corosync_tpg_group *groups, size_t groups_cnt, const struct iovec *iovec, unsigned int iov_len); int (*tpg_groups_release) ( int reserved_msgs); int (*schedwrk_create) ( hdb_handle_t *handle, int (schedwrk_fn) (const void *), const void *context); void (*schedwrk_destroy) (hdb_handle_t handle); int (*sync_request) ( const char *service_name); /* * User plugin-callable functions for quorum */ int (*quorum_is_quorate) (void); int (*quorum_register_callback) (quorum_callback_fn_t callback_fn, void *context); int (*quorum_unregister_callback) (quorum_callback_fn_t callback_fn, void *context); /* * This one is for the quorum management plugin's use */ int (*quorum_initialize)(struct quorum_callin_functions *fns); /* * Plugin loading and unloading */ int (*plugin_interface_reference) ( hdb_handle_t *handle, const char *iface_name, int version, void **interface, void *context); int (*plugin_interface_release) (hdb_handle_t handle); /* * Service loading and unloading APIs */ unsigned int (*service_link_and_init) ( struct corosync_api_v1 *corosync_api_v1, const char *service_name, unsigned int service_ver); unsigned int (*service_unlink_and_exit) ( struct corosync_api_v1 *corosync_api_v1, const char *service_name, unsigned int service_ver); /* * Error handling APIs */ void (*error_memory_failure) (void) __attribute__ ((noreturn)); #define corosync_fatal_error(err) api->fatal_error ((err), __FILE__, __LINE__) void (*fatal_error) (cs_fatal_error_t err, const char *file, unsigned int line) __attribute__ ((noreturn)); void (*shutdown_request) (void); void (*state_dump) (void); qb_loop_t *(*poll_handle_get) (void); void *(*totem_get_stats)(void); int (*schedwrk_create_nolock) ( hdb_handle_t *handle, int (schedwrk_fn) (const void *), const void *context); int (*poll_dispatch_add) (qb_loop_t * handle, int fd, int events, void *data, int (*dispatch_fn) (int fd, int revents, void *data)); int (*poll_dispatch_delete) ( qb_loop_t * handle, int fd); }; #define SERVICE_ID_MAKE(a,b) ( ((a)<<16) | (b) ) #define SERVICE_HANDLER_MAXIMUM_COUNT 64 #define SERVICES_COUNT_MAX 64 /** * @brief The corosync_lib_handler struct */ struct corosync_lib_handler { void (*lib_handler_fn) (void *conn, const void *msg); enum cs_lib_flow_control flow_control; }; /** * @brief The corosync_exec_handler struct */ struct corosync_exec_handler { void (*exec_handler_fn) (const void *msg, unsigned int nodeid); void (*exec_endian_convert_fn) (void *msg); }; /** * @brief The corosync_service_engine_iface_ver0 struct */ struct corosync_service_engine_iface_ver0 { struct corosync_service_engine *(*corosync_get_service_engine_ver0) (void); }; /** * @brief The corosync_service_engine struct */ struct corosync_service_engine { const char *name; unsigned short id; unsigned short priority; /* Lower priority are loaded first, unloaded last. * 0 is a special case which always loaded _and_ unloaded last */ size_t private_data_size; enum cs_lib_flow_control flow_control; enum cs_lib_allow_inquorate allow_inquorate; char *(*exec_init_fn) (struct corosync_api_v1 *); int (*exec_exit_fn) (void); void (*exec_dump_fn) (void); int (*lib_init_fn) (void *conn); int (*lib_exit_fn) (void *conn); struct corosync_lib_handler *lib_engine; int lib_engine_count; struct corosync_exec_handler *exec_engine; int exec_engine_count; int (*config_init_fn) (struct corosync_api_v1 *); void (*confchg_fn) ( enum totem_configuration_type configuration_type, const unsigned int *member_list, size_t member_list_entries, const unsigned int *left_list, size_t left_list_entries, const unsigned int *joined_list, size_t joined_list_entries, const struct memb_ring_id *ring_id); void (*sync_init) ( const unsigned int *trans_list, size_t trans_list_entries, const unsigned int *member_list, size_t member_list_entries, const struct memb_ring_id *ring_id); int (*sync_process) (void); void (*sync_activate) (void); void (*sync_abort) (void); }; #endif /* COROAPI_H_DEFINED */ diff --git a/include/corosync/totem/totemip.h b/include/corosync/totem/totemip.h index 61e3fc10..842e8e9e 100644 --- a/include/corosync/totem/totemip.h +++ b/include/corosync/totem/totemip.h @@ -1,132 +1,131 @@ /* * Copyright (c) 2005-2019 Red Hat, Inc. * * All rights reserved. * * Author: Patrick Caulfield (pcaulfie@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /* IPv4/6 abstraction */ #ifndef TOTEMIP_H_DEFINED #define TOTEMIP_H_DEFINED #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #ifdef SO_NOSIGPIPE #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif void totemip_nosigpipe(int s); #else #define totemip_nosigpipe(s) #endif #define TOTEMIP_ADDRLEN (sizeof(struct in6_addr)) /* These are the things that get passed around */ #define TOTEM_IP_ADDRESS struct totem_ip_address { unsigned int nodeid; unsigned short family; unsigned char addr[TOTEMIP_ADDRLEN]; - unsigned int sin6_scope_id; } __attribute__((packed)); enum totem_ip_version_enum { TOTEM_IP_VERSION_4, /* Use only AF_INET */ TOTEM_IP_VERSION_6, /* Use only AF_INET6 */ TOTEM_IP_VERSION_4_6, /* Use AF_UNSPEC and filter result preferring AF_INET */ TOTEM_IP_VERSION_6_4 /* Use AF_UNSPEC and filter result preferring AF_INET6 */ }; struct totem_ip_if_address { struct totem_ip_address ip_addr; struct totem_ip_address mask_addr; int interface_up; int interface_num; char *name; struct qb_list_head list; }; extern int totemip_equal(const struct totem_ip_address *addr1, const struct totem_ip_address *addr2); extern int totemip_sa_equal(const struct totem_ip_address *totem_ip, const struct sockaddr *sa); extern int totemip_compare(const void *a, const void *b); extern int totemip_is_mcast(struct totem_ip_address *addr); extern void totemip_copy(struct totem_ip_address *addr1, const struct totem_ip_address *addr2); int totemip_localhost(int family, struct totem_ip_address *localhost); extern int totemip_localhost_check(const struct totem_ip_address *addr); extern const char *totemip_print(const struct totem_ip_address *addr); extern const char *totemip_sa_print(const struct sockaddr *sa); extern int totemip_sockaddr_to_totemip_convert(const struct sockaddr_storage *saddr, struct totem_ip_address *ip_addr); extern int totemip_totemip_to_sockaddr_convert(struct totem_ip_address *ip_addr, uint16_t port, struct sockaddr_storage *saddr, int *addrlen); extern int totemip_parse(struct totem_ip_address *totemip, const char *addr, enum totem_ip_version_enum ip_version); extern int totemip_iface_check(struct totem_ip_address *bindnet, struct totem_ip_address *boundto, int *interface_up, int *interface_num, int mask_high_bit); extern int totemip_getifaddrs(struct qb_list_head *addrs); extern void totemip_freeifaddrs(struct qb_list_head *addrs); /* These two simulate a zero in_addr by clearing the family field */ static inline void totemip_zero_set(struct totem_ip_address *addr) { addr->family = 0; } static inline int totemip_zero_check(const struct totem_ip_address *addr) { return (addr->family == 0); } extern size_t totemip_udpip_header_size(int family); #ifdef __cplusplus } #endif #endif