Note: "permalinks" may not be as permanent as we would like,
direct links of old sources may well be a few messages off.
After hacking show_address() in user/drbdsetup.c, I managed to get "drbdsetup 0
show" to produce correct results:
...snip...
protocol C;
_this_host {
device minor 0;
disk "/dev/sda1";
meta-disk internal;
address ipv4 172.16.3.1:7788;
}
_remote_host {
address ipv4 172.16.3.2:7788;
}
The trick was to reserve a guaranteed-to-be-aligned buffer for the
sockaddr/sockaddr_in/sockaddr_in6 data and memcpy() to the buffer before
parsing it.
Here is the diff:
------------------------------------------------------------------------
--- user/drbdsetup.c.ORIG 2012-02-21 16:15:30.000000000 +0100
+++ user/drbdsetup.c 2012-03-13 15:09:06.000000000 +0100
@@ -1452,28 +1452,29 @@
static void show_address(void* address, int addr_len)
{
- struct sockaddr *addr;
struct sockaddr_in *addr4;
struct sockaddr_in6 *addr6;
char buffer[INET6_ADDRSTRLEN];
- addr = (struct sockaddr *)address;
- if (addr->sa_family == AF_INET
- || addr->sa_family == get_af_ssocks(0)
- || addr->sa_family == AF_INET_SDP) {
- addr4 = (struct sockaddr_in *)address;
+ struct sockaddr addrbuf; /* reserve a perfectly-aligned sockaddr */
+ memcpy(&addrbuf, address, addr_len); /* ...and fill it with bytes */
+
+ if (addrbuf.sa_family == AF_INET
+ || addrbuf.sa_family == get_af_ssocks(0)
+ || addrbuf.sa_family == AF_INET_SDP) {
+ addr4 = (struct sockaddr_in *)(&addrbuf);
printf("\taddress\t\t\t%s %s:%d;\n",
af_to_str(addr4->sin_family),
inet_ntoa(addr4->sin_addr),
ntohs(addr4->sin_port));
- } else if (addr->sa_family == AF_INET6) {
- addr6 = (struct sockaddr_in6 *)address;
+ } else if (addrbuf.sa_family == AF_INET6) {
+ addr6 = (struct sockaddr_in6 *)(&addrbuf);
printf("\taddress\t\t\t%s [%s]:%d;\n",
af_to_str(addr6->sin6_family),
inet_ntop(addr6->sin6_family, &addr6->sin6_addr, buffer, INET6_ADDRSTRLEN),
ntohs(addr6->sin6_port));
} else {
- printf("\taddress\t\t\t[unknown af=%d, len=%d]\n", addr->sa_family, addr_len);
+ printf("\taddress\t\t\t[unknown af=%d, len=%d]\n", addrbuf.sa_family, addr_len);
}
}
------------------------------------------------------------------------
gcc whines a bit:
drbdsetup.c: In function ‘show_address’:
drbdsetup.c:1466: warning: dereferencing pointer ‘addr4’ does break strict-aliasing rules
drbdsetup.c:1465: note: initialized from here
drbdsetup.c:1475: warning: dereferencing pointer ‘addr6’ does break strict-aliasing rules
drbdsetup.c:1474: warning: dereferencing pointer ‘addr6’ does break strict-aliasing rules
drbdsetup.c:1473: warning: dereferencing pointer ‘addr6’ does break strict-aliasing rules
drbdsetup.c:1471: note: initialized from here
cc1: warning: dereferencing pointer ‘addr6’ does break strict-aliasing rules
cc1: warning: dereferencing pointer ‘addr6’ does break strict-aliasing rules
cc1: warning: dereferencing pointer ‘addr6’ does break strict-aliasing rules
drbdsetup.c:1471: note: initialized from here
so it would be nice if some more-experienced C programmers found a cleaner
solution for aligning and conditionally-parsing the sockaddr structures.
Perhaps a union?
I am still interested to know if I am the only armel user having problems with
"drbdsetup 0 show"...
--
Erik Rossen
rossen at rossen.ch
http://www.rtfm-sarl.ch
OpenPGP key: 2935D0B9