ctdb-protocol: Add generalised socket address comparison
authorMartin Schwenke <martin@meltin.net>
Mon, 23 May 2016 00:35:10 +0000 (10:35 +1000)
committerAmitay Isaacs <amitay@samba.org>
Fri, 16 Dec 2016 07:42:32 +0000 (08:42 +0100)
Add new function ctdb_sock_addr_cmp(), which returns a 3-way result
useful for qsort(3).  Reimplent ctdb_sock_addr_same() using this.

In the process, make arguments const so that ctdb_sock_addr_cmp() can
be used with qsort().

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12470

Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
ctdb/protocol/protocol_api.h
ctdb/protocol/protocol_util.c

index e438e1dfc72b559a911b98d4cab523bcf76722e3..e967dea5a21e55157a0ce3da0589c1fe69d91ba6 100644 (file)
@@ -658,7 +658,13 @@ const char *ctdb_event_to_string(enum ctdb_event event);
 enum ctdb_event ctdb_event_from_string(const char *event_str);
 
 const char *ctdb_sock_addr_to_string(TALLOC_CTX *mem_ctx, ctdb_sock_addr *addr);
-bool ctdb_sock_addr_same_ip(ctdb_sock_addr *addr1, ctdb_sock_addr *addr2);
-bool ctdb_sock_addr_same(ctdb_sock_addr *addr1, ctdb_sock_addr *addr2);
+int ctdb_sock_addr_cmp_ip(const ctdb_sock_addr *addr1,
+                         const ctdb_sock_addr *addr2);
+int ctdb_sock_addr_cmp(const ctdb_sock_addr *addr1,
+                      const ctdb_sock_addr *addr2);
+bool ctdb_sock_addr_same_ip(const ctdb_sock_addr *addr1,
+                           const ctdb_sock_addr *addr2);
+bool ctdb_sock_addr_same(const ctdb_sock_addr *addr1,
+                        const ctdb_sock_addr *addr2);
 
 #endif /* __CTDB_PROTOCOL_API_H__ */
index b91c652251f9cc0aeea1dc6f10402c436642ff2e..0e1bf286799f117c3276bd974baf183dc8cb85f0 100644 (file)
@@ -141,55 +141,81 @@ const char *ctdb_sock_addr_to_string(TALLOC_CTX *mem_ctx, ctdb_sock_addr *addr)
        return cip;
 }
 
-bool ctdb_sock_addr_same_ip(ctdb_sock_addr *addr1, ctdb_sock_addr *addr2)
+int ctdb_sock_addr_cmp_ip(const ctdb_sock_addr *addr1,
+                         const ctdb_sock_addr *addr2)
 {
-       if (addr1->sa.sa_family != addr2->sa.sa_family) {
-               return false;
+       int ret = 0;
+
+       /* This is somewhat arbitrary.  However, when used for sorting
+        * it just needs to be consistent.
+        */
+       if (addr1->sa.sa_family < addr2->sa.sa_family) {
+               return -1;
+       }
+       if (addr1->sa.sa_family > addr2->sa.sa_family) {
+               return 1;
        }
 
        switch (addr1->sa.sa_family) {
        case AF_INET:
-               if (addr1->ip.sin_addr.s_addr != addr2->ip.sin_addr.s_addr) {
-                       return false;
-               }
+               ret = memcmp(&addr1->ip.sin_addr.s_addr,
+                            &addr2->ip.sin_addr.s_addr, 4);
                break;
 
        case AF_INET6:
-               if (memcmp(addr1->ip6.sin6_addr.s6_addr,
-                          addr2->ip6.sin6_addr.s6_addr, 16) != 0) {
-                       return false;
-               }
+               ret = memcmp(addr1->ip6.sin6_addr.s6_addr,
+                            addr2->ip6.sin6_addr.s6_addr, 16);
                break;
 
        default:
-               return false;
+               ret = -1;
        }
 
-       return true;
+       return ret;
 }
 
-bool ctdb_sock_addr_same(ctdb_sock_addr *addr1, ctdb_sock_addr *addr2)
+int ctdb_sock_addr_cmp(const ctdb_sock_addr *addr1,
+                      const ctdb_sock_addr *addr2)
 {
-       if (! ctdb_sock_addr_same_ip(addr1, addr2)) {
-               return false;
+       int ret = 0;
+
+       ret = ctdb_sock_addr_cmp_ip(addr1, addr2);
+       if (ret != 0) {
+               return ret;
        }
 
        switch (addr1->sa.sa_family) {
        case AF_INET:
-               if (addr1->ip.sin_port != addr2->ip.sin_port) {
-                       return false;
+               if (addr1->ip.sin_port < addr2->ip.sin_port) {
+                       ret = -1;
+               } else if (addr1->ip.sin_port > addr2->ip.sin_port) {
+                       ret = 1;
                }
                break;
 
        case AF_INET6:
-               if (addr1->ip6.sin6_port != addr2->ip6.sin6_port) {
-                       return false;
+               if (addr1->ip6.sin6_port < addr2->ip6.sin6_port) {
+                       ret = -1;
+               } else if (addr1->ip6.sin6_port > addr2->ip6.sin6_port) {
+                       ret = 1;
                }
                break;
 
        default:
-               return false;
+               ret = -1;
        }
 
-       return true;
+       return ret;
+}
+
+bool ctdb_sock_addr_same_ip(const ctdb_sock_addr *addr1,
+                           const ctdb_sock_addr *addr2)
+{
+       return (ctdb_sock_addr_cmp_ip(addr1, addr2) == 0);
+}
+
+bool ctdb_sock_addr_same(const ctdb_sock_addr *addr1,
+                        const ctdb_sock_addr *addr2)
+{
+       return (ctdb_sock_addr_cmp(addr1, addr2) == 0);
 }