s3:ctdbd_conn: canonicalize ips before sending them to ctdbd
authorStefan Metzmacher <metze@samba.org>
Wed, 28 Jan 2009 17:55:13 +0000 (18:55 +0100)
committerStefan Metzmacher <metze@samba.org>
Thu, 29 Jan 2009 16:40:13 +0000 (17:40 +0100)
This makes samba work with older ctdb versions.

metze

source3/lib/ctdbd_conn.c

index f8dae8fbd6ce755e0a863659560015e5121282f2..88d82caab83f25912dbf450bd364c13156851add 100644 (file)
@@ -1176,46 +1176,76 @@ NTSTATUS ctdbd_traverse(uint32 db_id,
        return status;
 }
 
+/*
+   This is used to canonicalize a ctdb_sock_addr structure.
+*/
+static void smbd_ctdb_canonicalize_ip(const struct sockaddr_storage *in,
+                                     struct sockaddr_storage *out)
+{
+       memcpy(out, in, sizeof (*out));
+
+#ifdef HAVE_IPV6
+       if (in->ss_family == AF_INET6) {
+               const char prefix[12] = { 0,0,0,0,0,0,0,0,0,0,0xff,0xff };
+               const struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)in;
+               struct sockaddr_in *out4 = (struct sockaddr_in *)out;
+               if (memcmp(&in6->sin6_addr, prefix, 12) == 0) {
+                       memset(out, 0, sizeof(*out));
+#ifdef HAVE_SOCK_SIN_LEN
+                       out4->sin_len = sizeof(*out);
+#endif
+                       out4->sin_family = AF_INET;
+                       out4->sin_port   = in6->sin6_port;
+                       memcpy(&out4->sin_addr, &in6->sin6_addr.s6_addr32[3], 4);
+               }
+       }
+#endif
+}
+
 /*
  * Register us as a server for a particular tcp connection
  */
 
 NTSTATUS ctdbd_register_ips(struct ctdbd_connection *conn,
-                           const struct sockaddr_storage *server,
-                           const struct sockaddr_storage *client,
+                           const struct sockaddr_storage *_server,
+                           const struct sockaddr_storage *_client,
                            void (*release_ip_handler)(const char *ip_addr,
                                                       void *private_data),
                            void *private_data)
 {
-       struct sockaddr *sock = (struct sockaddr *)client;
        /*
         * we still use ctdb_control_tcp for ipv4
         * because we want to work against older ctdb
         * versions at runtime
         */
        struct ctdb_control_tcp p4;
-#ifdef HAVE_IPV6
+#ifdef HAVE_STRUCT_CTDB_CONTROL_TCP_ADDR
        struct ctdb_control_tcp_addr p;
 #endif
        TDB_DATA data;
        NTSTATUS status;
+       struct sockaddr_storage client;
+       struct sockaddr_storage server;
 
        /*
         * Only one connection so far
         */
        SMB_ASSERT(conn->release_ip_handler == NULL);
 
-       switch (sock->sa_family) {
+       smbd_ctdb_canonicalize_ip(_client, &client);
+       smbd_ctdb_canonicalize_ip(_server, &server);
+
+       switch (client.ss_family) {
        case AF_INET:
-               p4.dest = *(struct sockaddr_in *)server;
-               p4.src = *(struct sockaddr_in *)client;
+               p4.dest = *(struct sockaddr_in *)&server;
+               p4.src = *(struct sockaddr_in *)&client;
                data.dptr = (uint8_t *)&p4;
                data.dsize = sizeof(p4);
                break;
-#ifdef HAVE_IPV6
+#ifdef HAVE_STRUCT_CTDB_CONTROL_TCP_ADDR
        case AF_INET6:
-               p.dest.ip6 = *(struct sockaddr_in6 *)server;
-               p.src.ip6 = *(struct sockaddr_in6 *)client;
+               p.dest.ip6 = *(struct sockaddr_in6 *)&server;
+               p.src.ip6 = *(struct sockaddr_in6 *)&client;
                data.dptr = (uint8_t *)&p;
                data.dsize = sizeof(p);
                break;