defect 981

big endian and little endian in the same network causes infinite loop.  This
patch fixes that problem for the totem layer only.  Other components are not
resolved.


git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@922 fd59a12c-fef9-0310-b244-a6a79926bd2f
This commit is contained in:
Steven Dake 2006-02-11 22:25:54 +00:00
parent e7abe20d67
commit d248cfb8ae
5 changed files with 97 additions and 68 deletions

View File

@ -36,12 +36,9 @@
#include <sys/socket.h>
#include <netdb.h>
#include <sys/un.h>
#include <sys/sysinfo.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/if.h>
#include <linux/sockios.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
@ -55,31 +52,31 @@
#define swab16(x) \
({ \
__u16 __x = (x); \
((__u16)( \
(((__u16)(__x) & (__u16)0x00ffU) << 8) | \
(((__u16)(__x) & (__u16)0xff00U) >> 8) )); \
uint16_t __x = (x); \
((uint16_t)( \
(((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
(((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
})
#define swab32(x) \
({ \
__u32 __x = (x); \
((__u32)( \
(((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \
(((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \
(((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \
(((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \
uint32_t __x = (x); \
((uint32_t)( \
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
})
#define swab64(x) \
({ \
__u64 __x = (x); \
((__u64)( \
(__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \
(__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \
(__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \
(__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \
(__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \
(__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
(__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \
(__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \
uint64_t __x = (x); \
((uint64_t)( \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
})

View File

@ -61,7 +61,7 @@
#define CONSENSUS_TIMEOUT 200
#define MERGE_TIMEOUT 200
#define DOWNCHECK_TIMEOUT 1000
#define FAIL_TO_RECV_CONST 10
#define FAIL_TO_RECV_CONST 50
#define SEQNO_UNCHANGED_CONST 30
#define MINIMUM_TIMEOUT (int)(1000/HZ)*3
#define MAX_NETWORK_DELAY 50 /*In milliseconds*/

View File

@ -51,6 +51,7 @@
#include <linux/rtnetlink.h>
#include "totemip.h"
#include "swab.h"
#define LOCALHOST_IPV4 "127.0.0.1"
#define LOCALHOST_IPV6 "::1"
@ -86,6 +87,13 @@ void totemip_copy(struct totem_ip_address *addr1, struct totem_ip_address *addr2
memcpy(addr1, addr2, sizeof(struct totem_ip_address));
}
void totemip_copy_endian_convert(struct totem_ip_address *addr1, struct totem_ip_address *addr2)
{
addr1->nodeid = swab32(addr2->nodeid);
addr1->family = swab16(addr2->family);
memcpy(addr1->addr, addr2->addr, TOTEMIP_ADDRLEN);
}
/* For sorting etc. params are void * for qsort's benefit */
int totemip_compare(const void *a, const void *b)
{

View File

@ -51,6 +51,7 @@ struct totem_ip_address
extern int totemip_equal(struct totem_ip_address *addr1, struct totem_ip_address *addr2);
extern int totemip_compare(const void *a, const void *b);
extern void totemip_copy(struct totem_ip_address *addr1, struct totem_ip_address *addr2);
extern void totemip_copy_endian_convert(struct totem_ip_address *addr1, struct totem_ip_address *addr2);
int totemip_localhost(int family, struct totem_ip_address *localhost);
extern int totemip_localhost_check(struct totem_ip_address *addr);
extern const char *totemip_print(struct totem_ip_address *addr);

View File

@ -526,6 +526,9 @@ static void orf_token_endian_convert (struct orf_token *in, struct orf_token *ou
static void memb_commit_token_endian_convert (struct memb_commit_token *in, struct memb_commit_token *out);
static void memb_join_endian_convert (struct memb_join *in, struct memb_join *out);
static void mcast_endian_convert (struct mcast *in, struct mcast *out);
static void memb_merge_detect_endian_convert (
struct memb_merge_detect *in,
struct memb_merge_detect *out);
static void timer_function_orf_token_timeout (void *data);
static void timer_function_heartbeat_timeout (void *data);
static void timer_function_token_retransmit_timeout (void *data);
@ -2686,8 +2689,7 @@ static int message_handler_orf_token (
{
char token_storage[1500];
char token_convert[1500];
struct orf_token *token;
struct orf_token *token_ref = (struct orf_token *)msg;
struct orf_token *token = NULL;
int transmits_allowed;
int forward_token;
int mcasted;
@ -2713,20 +2715,12 @@ if (random()%100 < 10) {
}
#endif
/*
* Handle merge detection timeout
*/
if (token_ref->seq == instance->my_last_seq) {
start_merge_detect_timeout (instance);
instance->my_seq_unchanged += 1;
} else {
cancel_merge_detect_timeout (instance);
cancel_token_hold_retransmit_timeout (instance);
instance->my_seq_unchanged = 0;
if (endian_conversion_needed) {
orf_token_endian_convert ((struct orf_token *)msg,
(struct orf_token *)token_convert);
msg = (struct orf_token *)token_convert;
}
instance->my_last_seq = token_ref->seq;
/*
* Make copy of token and retransmit list in case we have
* to flush incoming messages from the kernel queue
@ -2736,11 +2730,21 @@ if (random()%100 < 10) {
memcpy (&token->rtr_list[0], msg + sizeof (struct orf_token),
sizeof (struct rtr_item) * RETRANSMIT_ENTRIES_MAX);
if (endian_conversion_needed) {
orf_token_endian_convert (token, (struct orf_token *)token_convert);
token = (struct orf_token *)token_convert;
/*
* Handle merge detection timeout
*/
if (token->seq == instance->my_last_seq) {
start_merge_detect_timeout (instance);
instance->my_seq_unchanged += 1;
} else {
cancel_merge_detect_timeout (instance);
cancel_token_hold_retransmit_timeout (instance);
instance->my_seq_unchanged = 0;
}
instance->my_last_seq = token->seq;
totemrrp_recv_flush (instance->totemrrp_handle);
/*
@ -2830,7 +2834,6 @@ if (random()%100 < 10) {
if (sq_lt_compare (instance->last_released + MISSING_MCAST_WINDOW, token->seq + TRANSMITS_ALLOWED)) {
transmits_allowed = 0;
printf ("zero \n");
}
mcasted = orf_token_mcast (instance, token, transmits_allowed, system_from);
if (sq_lt_compare (instance->my_aru, token->aru) ||
@ -2983,6 +2986,7 @@ static void messages_deliver_to_app (
struct mcast *mcast;
unsigned int range = 0;
unsigned int my_high_delivered_stored = 0;
struct totem_ip_address msg_source;
instance->totemsrp_log_printf (instance->totemsrp_log_level_debug,
"Delivering %x to %x\n", instance->my_high_delivered,
@ -3050,13 +3054,19 @@ static void messages_deliver_to_app (
"Delivering MCAST message with seq %x to pending delivery queue\n",
mcast->seq);
if (mcast->header.endian_detector == ENDIAN_LOCAL) {
totemip_copy (&msg_source, &mcast->source);
} else {
totemip_copy_endian_convert (&msg_source, &mcast->source);
}
/*
* Message is locally originated multicast
*/
if (sort_queue_item_p->iov_len > 1 &&
sort_queue_item_p->iovec[0].iov_len == sizeof (struct mcast)) {
instance->totemsrp_deliver_fn (
&mcast->source,
&msg_source,
&sort_queue_item_p->iovec[1],
sort_queue_item_p->iov_len - 1,
mcast->header.endian_detector != ENDIAN_LOCAL);
@ -3065,7 +3075,7 @@ static void messages_deliver_to_app (
sort_queue_item_p->iovec[0].iov_base += sizeof (struct mcast);
instance->totemsrp_deliver_fn (
&mcast->source,
&msg_source,
sort_queue_item_p->iovec,
sort_queue_item_p->iov_len,
mcast->header.endian_detector != ENDIAN_LOCAL);
@ -3220,6 +3230,10 @@ static int message_handler_memb_merge_detect (
{
struct memb_merge_detect *memb_merge_detect = (struct memb_merge_detect *)msg;
if (endian_conversion_needed) {
memb_merge_detect_endian_convert (msg, msg);
}
/*
* do nothing if this is a merge detect from this configuration
*/
@ -3341,12 +3355,10 @@ static void memb_join_endian_convert (struct memb_join *in, struct memb_join *ou
out->failed_list_entries = swab32 (in->failed_list_entries);
out->ring_seq = swab64 (in->ring_seq);
for (i = 0; i < out->proc_list_entries; i++) {
totemip_copy(&out->proc_list[i], &in->proc_list[i]);
out->proc_list[i].family = swab16(out->proc_list[i].family);
totemip_copy_endian_convert(&out->proc_list[i], &in->proc_list[i]);
}
for (i = 0; i < out->failed_list_entries; i++) {
totemip_copy(&out->failed_list[i], &in->failed_list[i]);
out->failed_list[i].family = swab16(out->failed_list[i].family);
totemip_copy_endian_convert(&out->failed_list[i], &in->failed_list[i]);
}
}
@ -3358,24 +3370,27 @@ static void memb_commit_token_endian_convert (struct memb_commit_token *in, stru
out->header.endian_detector = ENDIAN_LOCAL;
out->header.nodeid = swab32 (in->header.nodeid);
out->token_seq = swab32 (in->token_seq);
totemip_copy(&out->ring_id.rep, &in->ring_id.rep);
totemip_copy_endian_convert(&out->ring_id.rep, &in->ring_id.rep);
out->ring_id.seq = swab64 (in->ring_id.seq);
out->retrans_flg = swab32 (in->retrans_flg);
out->memb_index = swab32 (in->memb_index);
out->addr_entries = swab32 (in->addr_entries);
for (i = 0; i < out->addr_entries; i++) {
totemip_copy(&out->addr[i], &in->addr[i]);
out->addr[i].family = swab16(in->addr[i].family);
totemip_copy_endian_convert(&out->addr[i], &in->addr[i]);
totemip_copy(&out->memb_list[i].ring_id.rep,
&in->memb_list[i].ring_id.rep);
out->memb_list[i].ring_id.rep.family = swab16(in->memb_list[i].ring_id.rep.family);
out->memb_list[i].ring_id.seq =
swab64 (in->memb_list[i].ring_id.seq);
out->memb_list[i].aru = swab32 (in->memb_list[i].aru);
out->memb_list[i].high_delivered = swab32 (in->memb_list[i].high_delivered);
out->memb_list[i].received_flg = swab32 (in->memb_list[i].received_flg);
/*
* Only convert the memb entry if it has been set
*/
if (in->memb_list[i].ring_id.rep.family != 0) {
totemip_copy_endian_convert(&out->memb_list[i].ring_id.rep,
&in->memb_list[i].ring_id.rep);
out->memb_list[i].ring_id.seq =
swab64 (in->memb_list[i].ring_id.seq);
out->memb_list[i].aru = swab32 (in->memb_list[i].aru);
out->memb_list[i].high_delivered = swab32 (in->memb_list[i].high_delivered);
out->memb_list[i].received_flg = swab32 (in->memb_list[i].received_flg);
}
}
}
@ -3389,16 +3404,14 @@ static void orf_token_endian_convert (struct orf_token *in, struct orf_token *ou
out->seq = swab32 (in->seq);
out->token_seq = swab32 (in->token_seq);
out->aru = swab32 (in->aru);
totemip_copy(&out->ring_id.rep, &in->ring_id.rep);
out->ring_id.rep.family = swab16(in->ring_id.rep.family);
totemip_copy_endian_convert(&out->ring_id.rep, &in->ring_id.rep);
totemip_copy_endian_convert(&out->aru_addr, &in->aru_addr);
out->ring_id.seq = swab64 (in->ring_id.seq);
out->fcc = swab32 (in->fcc);
out->retrans_flg = swab32 (in->retrans_flg);
out->rtr_list_entries = swab32 (in->rtr_list_entries);
for (i = 0; i < out->rtr_list_entries; i++) {
totemip_copy(&out->rtr_list[i].ring_id.rep, &in->rtr_list[i].ring_id.rep);
out->rtr_list[i].ring_id.rep.family = swab16(in->rtr_list[i].ring_id.rep.family);
totemip_copy_endian_convert(&out->rtr_list[i].ring_id.rep, &in->rtr_list[i].ring_id.rep);
out->rtr_list[i].ring_id.seq = swab64 (in->rtr_list[i].ring_id.seq);
out->rtr_list[i].seq = swab32 (in->rtr_list[i].seq);
}
@ -3410,13 +3423,23 @@ static void mcast_endian_convert (struct mcast *in, struct mcast *out)
out->header.endian_detector = ENDIAN_LOCAL;
out->header.nodeid = swab32 (in->header.nodeid);
out->seq = swab32 (in->seq);
totemip_copy(&out->ring_id.rep, &in->ring_id.rep);
out->ring_id.rep.family = swab16(in->ring_id.rep.family);
totemip_copy_endian_convert(&out->ring_id.rep, &in->ring_id.rep);
totemip_copy_endian_convert(&out->source, &in->source);
out->ring_id.seq = swab64 (in->ring_id.seq);
out->source = in->source;
out->guarantee = in->guarantee;
}
static void memb_merge_detect_endian_convert (
struct memb_merge_detect *in,
struct memb_merge_detect *out)
{
out->header.type = in->header.type;
out->header.endian_detector = ENDIAN_LOCAL;
out->header.nodeid = swab32 (in->header.nodeid);
totemip_copy_endian_convert(&out->ring_id.rep, &in->ring_id.rep);
out->ring_id.seq = swab64 (in->ring_id.seq);
}
static int message_handler_memb_join (
struct totemsrp_instance *instance,
struct totem_ip_address *system_from,