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
[email protected]
http://www.rtfm-sarl.ch
OpenPGP key: 2935D0B9
_______________________________________________
drbd-user mailing list
[email protected]
http://lists.linbit.com/mailman/listinfo/drbd-user

Reply via email to